android: Update app-specific/MIME type icons
[LibreOffice.git] / filter / source / msfilter / svdfppt.cxx
blob3847c12264a5078291b58417ee02bc32e0f2b7d6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <osl/endian.h>
23 #include <utility>
24 #include <vcl/svapp.hxx>
25 #include <unotools/tempfile.hxx>
26 #include <comphelper/diagnose_ex.hxx>
27 #include <tools/UnitConversion.hxx>
28 #include <editeng/eeitem.hxx>
29 #include <editeng/editdata.hxx>
30 #include <sot/storage.hxx>
31 #include <sot/storinfo.hxx>
32 #include <sot/stg.hxx>
33 #include <com/sun/star/embed/Aspects.hpp>
34 #include <com/sun/star/embed/XEmbeddedObject.hpp>
35 #include <com/sun/star/frame/XModel.hpp>
36 #include <com/sun/star/office/XAnnotation.hpp>
37 #include <com/sun/star/office/XAnnotationAccess.hpp>
38 #include <com/sun/star/text/XText.hpp>
39 #include <com/sun/star/geometry/RealPoint2D.hpp>
40 #include <com/sun/star/util/DateTime.hpp>
41 #include <com/sun/star/drawing/BitmapMode.hpp>
42 #include <filter/msfilter/svdfppt.hxx>
43 #include <svx/xflgrit.hxx>
44 #include <svx/xbtmpit.hxx>
45 #include <svx/svdtrans.hxx>
46 #include <svx/svdmodel.hxx>
47 #include <svx/svdpage.hxx>
48 #include <svx/svdobj.hxx>
49 #include <svx/svdogrp.hxx>
50 #include <svx/svdorect.hxx>
51 #include <svx/svdopage.hxx>
52 #include <svx/svdograf.hxx>
53 #include <svx/svdopath.hxx>
54 #include <svx/svdotable.hxx>
55 #include <svx/xfillit0.hxx>
56 #include <svx/xfilluseslidebackgrounditem.hxx>
57 #include <svx/xflbstit.hxx>
58 #include <svx/xflbmtit.hxx>
59 #include <svx/xflclit.hxx>
60 #include <svx/xfltrit.hxx>
61 #include <editeng/outlobj.hxx>
62 #include <editeng/numdef.hxx>
63 #include <svx/sdasitm.hxx>
64 #include <svx/sdmetitm.hxx>
65 #include <svx/sdtagitm.hxx>
66 #include <svx/sdtditm.hxx>
67 #include <svx/sdtfsitm.hxx>
68 #include <svx/sdtmfitm.hxx>
69 #include <svx/xlineit0.hxx>
70 #include <svx/xlnclit.hxx>
71 #include <svx/xlnwtit.hxx>
72 #include <editeng/hngpnctitem.hxx>
73 #include <editeng/forbiddenruleitem.hxx>
74 #include <svx/svdoashp.hxx>
75 #include <editeng/tstpitem.hxx>
76 #include <editeng/editids.hrc>
78 #include <editeng/adjustitem.hxx>
79 #include <editeng/escapementitem.hxx>
80 #include <editeng/colritem.hxx>
81 #include <editeng/fhgtitem.hxx>
82 #include <editeng/wghtitem.hxx>
83 #include <editeng/postitem.hxx>
84 #include <editeng/udlnitem.hxx>
85 #include <editeng/crossedoutitem.hxx>
86 #include <editeng/shdditem.hxx>
87 #include <editeng/charreliefitem.hxx>
88 #include <editeng/fontitem.hxx>
89 #include <svx/svdoutl.hxx>
90 #include <editeng/lspcitem.hxx>
91 #include <editeng/ulspitem.hxx>
92 #include <editeng/lrspitem.hxx>
93 #include <editeng/numitem.hxx>
94 #include <vcl/gdimtf.hxx>
95 #include <vcl/BitmapReadAccess.hxx>
96 #include <svx/svditer.hxx>
97 #include <editeng/flditem.hxx>
98 #include <tools/zcodec.hxx>
99 #include <filter/msfilter/svxmsbas.hxx>
100 #include <sfx2/objsh.hxx>
101 #include <editeng/brushitem.hxx>
102 #include <editeng/langitem.hxx>
103 #include <svx/svdoole2.hxx>
104 #include <toolkit/helper/vclunohelper.hxx>
105 #include <com/sun/star/container/XIndexContainer.hpp>
106 #include <com/sun/star/drawing/XControlShape.hpp>
107 #include <com/sun/star/form/XFormComponent.hpp>
108 #include <com/sun/star/beans/XPropertySet.hpp>
109 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
110 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
111 #include <com/sun/star/awt/Size.hpp>
112 #include <com/sun/star/drawing/FillStyle.hpp>
113 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
114 #include <editeng/frmdiritem.hxx>
115 #include <svx/sdtfchim.hxx>
116 #include <com/sun/star/awt/Gradient.hpp>
117 #include <com/sun/star/table/XMergeableCellRange.hpp>
118 #include <com/sun/star/table/BorderLine2.hpp>
119 #include <com/sun/star/table/BorderLineStyle.hpp>
120 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
121 #include <svtools/embedhlp.hxx>
122 #include <o3tl/enumrange.hxx>
123 #include <o3tl/safeint.hxx>
124 #include <o3tl/sorted_vector.hxx>
125 #include <sal/log.hxx>
127 #include <algorithm>
128 #include <cassert>
129 #include <rtl/strbuf.hxx>
130 #include <tools/time.hxx>
131 #include <memory>
133 // PPT ColorScheme Slots
134 #define PPT_COLSCHEME (0x08000000)
135 #define PPT_COLSCHEME_HINTERGRUND (0x08000000)
136 #define PPT_COLSCHEME_TEXT_UND_ZEILEN (0x08000001)
137 #define PPT_COLSCHEME_TITELTEXT (0x08000003)
138 #define PPT_COLSCHEME_A_UND_HYPERLINK (0x08000006)
140 #define ANSI_CHARSET 0
141 #define SYMBOL_CHARSET 2
143 /* Font Families */
144 #define FF_ROMAN 0x10
145 #define FF_SWISS 0x20
146 #define FF_MODERN 0x30
147 #define FF_SCRIPT 0x40
148 #define FF_DECORATIVE 0x50
150 #define DEFAULT_PITCH 0x00
151 #define FIXED_PITCH 0x01
152 #define VARIABLE_PITCH 0x02
154 using namespace ::com::sun::star ;
155 using namespace uno ;
156 using namespace beans ;
157 using namespace drawing ;
158 using namespace container ;
159 using namespace table ;
161 PowerPointImportParam::PowerPointImportParam( SvStream& rDocStrm ) :
162 rDocStream ( rDocStrm ),
163 nImportFlags ( 0 )
167 SvStream& ReadPptCurrentUserAtom( SvStream& rIn, PptCurrentUserAtom& rAtom )
169 DffRecordHeader aHd;
170 ReadDffRecordHeader( rIn, aHd );
171 if ( aHd.nRecType == PPT_PST_CurrentUserAtom )
173 sal_uInt32 nLen;
174 sal_uInt16 nUserNameLen(0), nPad;
175 rIn.ReadUInt32( nLen )
176 .ReadUInt32( rAtom.nMagic )
177 .ReadUInt32( rAtom.nCurrentUserEdit )
178 .ReadUInt16( nUserNameLen )
179 .ReadUInt16( rAtom.nDocFileVersion )
180 .ReadUChar( rAtom.nMajorVersion )
181 .ReadUChar( rAtom.nMinorVersion )
182 .ReadUInt16( nPad );
183 rAtom.aCurrentUser = SvxMSDffManager::MSDFFReadZString( rIn, nUserNameLen, true );
185 aHd.SeekToEndOfRecord( rIn );
186 return rIn;
189 void PptSlidePersistAtom::Clear()
191 nReserved = nPsrReference = nFlags = nNumberTexts = nSlideId = 0;
194 SvStream& ReadPptSlidePersistAtom( SvStream& rIn, PptSlidePersistAtom& rAtom )
196 DffRecordHeader aHd;
197 ReadDffRecordHeader( rIn, aHd );
199 .ReadUInt32( rAtom.nPsrReference )
200 .ReadUInt32( rAtom.nFlags )
201 .ReadUInt32( rAtom.nNumberTexts )
202 .ReadUInt32( rAtom.nSlideId );
203 aHd.SeekToEndOfRecord( rIn );
204 return rIn;
207 PptSlidePersistList::PptSlidePersistList() {}
209 PptSlidePersistList::~PptSlidePersistList() {}
211 sal_uInt16 PptSlidePersistList::FindPage(sal_uInt32 nId) const
213 for ( size_t i=0; i < mvEntries.size(); i++ )
215 if (mvEntries[ i ]->GetSlideId() == nId) return i;
217 return PPTSLIDEPERSIST_ENTRY_NOTFOUND;
220 SvStream& ReadPptInteractiveInfoAtom( SvStream& rIn, PptInteractiveInfoAtom& rAtom )
222 rIn.ReadUInt32( rAtom.nSoundRef )
223 .ReadUInt32( rAtom.nExHyperlinkId )
224 .ReadUChar( rAtom.nAction )
225 .ReadUChar( rAtom.nOleVerb )
226 .ReadUChar( rAtom.nJump )
227 .ReadUChar( rAtom.nFlags )
228 .ReadUChar( rAtom.nHyperlinkType )
229 .ReadUChar( rAtom.nUnknown1 )
230 .ReadUChar( rAtom.nUnknown2 )
231 .ReadUChar( rAtom.nUnknown3 );
232 return rIn;
235 SvStream& ReadPptExOleObjAtom( SvStream& rIn, PptExOleObjAtom& rAtom )
237 sal_uInt32 nDummy1;
238 sal_uInt32 nDummy2;
239 sal_uInt32 nDummy4;
241 rIn.ReadUInt32( rAtom.nAspect )
242 .ReadUInt32( nDummy1 )
243 .ReadUInt32( rAtom.nId )
244 .ReadUInt32( nDummy2 )
245 .ReadUInt32( rAtom.nPersistPtr )
246 .ReadUInt32( nDummy4 );
247 return rIn;
250 SvStream& ReadPptDocumentAtom(SvStream& rIn, PptDocumentAtom& rAtom)
252 // Actual format:
253 // 00 aSlidePageSizeXY 8
254 // 08 aNotesPageSizeXY 8
255 // 16 aZoomRatio (OLE) 8
256 // 24 nNotesMasterPersist 4
257 // 28 nHandoutMasterPersist 4
258 // 32 n1stPageNumber 2
259 // 34 ePageFormat 2
260 // 36 bEmbeddedTrueType 1
261 // 37 bOmitTitlePlace 1
262 // 38 bRightToLeft 1
263 // 39 bShowComments 1
265 DffRecordHeader aHd;
266 sal_Int32 nSlideX(0), nSlideY(0), nNoticeX(0), nNoticeY(0), nDummy;
267 sal_uInt16 nSlidePageFormat(0);
268 sal_Int8 nEmbeddedTrueType(0), nTitlePlaceHoldersOmitted(0), nRightToLeft(0), nShowComments(0);
270 ReadDffRecordHeader( rIn, aHd );
272 .ReadInt32( nSlideX ).ReadInt32( nSlideY )
273 .ReadInt32( nNoticeX ).ReadInt32( nNoticeY )
274 .ReadInt32( nDummy ).ReadInt32( nDummy ) // skip ZoomRatio
275 .ReadUInt32( rAtom.nNotesMasterPersist )
276 .ReadUInt32( rAtom.nHandoutMasterPersist )
277 .ReadUInt16( rAtom.n1stPageNumber )
278 .ReadUInt16( nSlidePageFormat )
279 .ReadSChar( nEmbeddedTrueType )
280 .ReadSChar( nTitlePlaceHoldersOmitted )
281 .ReadSChar( nRightToLeft )
282 .ReadSChar( nShowComments );
283 // clamp dodgy data to avoid overflow in later calculations
284 const sal_Int32 nPageClamp = SAL_MAX_INT32/5;
285 rAtom.aSlidesPageSize.setWidth( std::clamp<sal_Int32>(nSlideX, -nPageClamp, nPageClamp) );
286 rAtom.aSlidesPageSize.setHeight( std::clamp<sal_Int32>(nSlideY, -nPageClamp, nPageClamp) );
287 const sal_Int32 nNoteClamp = 65536;
288 rAtom.aNotesPageSize.setWidth( std::clamp<sal_Int32>(nNoticeX, -nNoteClamp, nNoteClamp) );
289 rAtom.aNotesPageSize.setHeight( std::clamp<sal_Int32>(nNoticeY, -nNoteClamp, nNoteClamp) );
290 rAtom.eSlidesPageFormat = static_cast<PptPageFormat>(nSlidePageFormat);
291 rAtom.bEmbeddedTrueType = nEmbeddedTrueType;
292 rAtom.bTitlePlaceholdersOmitted = nTitlePlaceHoldersOmitted;
293 rAtom.bRightToLeft = nRightToLeft;
294 rAtom.bShowComments = nShowComments;
295 aHd.SeekToEndOfRecord( rIn );
296 return rIn;
299 void PptSlideLayoutAtom::Clear()
301 eLayout = PptSlideLayout::TITLESLIDE;
302 for (PptPlaceholder & i : aPlaceholderId)
303 i = PptPlaceholder::NONE;
306 SvStream& ReadPptSlideLayoutAtom( SvStream& rIn, PptSlideLayoutAtom& rAtom )
308 sal_Int32 nTmp;
309 rIn.ReadInt32(nTmp);
310 rAtom.eLayout = static_cast<PptSlideLayout>(nTmp);
311 static_assert(sizeof(rAtom.aPlaceholderId) == 8, "wrong size of serialized array");
312 rIn.ReadBytes(rAtom.aPlaceholderId, 8);
313 return rIn;
316 SvStream& ReadPptSlideAtom( SvStream& rIn, PptSlideAtom& rAtom )
318 DffRecordHeader aHd;
319 ReadDffRecordHeader( rIn, aHd );
320 ReadPptSlideLayoutAtom( rIn, rAtom.aLayout );
321 rIn.ReadUInt32( rAtom.nMasterId )
322 .ReadUInt32( rAtom.nNotesId )
323 .ReadUInt16( rAtom.nFlags );
324 aHd.SeekToEndOfRecord( rIn );
325 return rIn;
328 void PptSlideAtom::Clear()
330 nMasterId = nNotesId = 0;
331 nFlags = 0;
334 SvStream& ReadPptNotesAtom( SvStream& rIn, PptNotesAtom& rAtom )
336 DffRecordHeader aHd;
337 ReadDffRecordHeader( rIn, aHd );
339 .ReadUInt32( rAtom.nSlideId )
340 .ReadUInt16( rAtom.nFlags );
341 aHd.SeekToEndOfRecord( rIn );
342 return rIn;
345 void PptNotesAtom::Clear()
347 nSlideId = 0;
348 nFlags = 0;
351 PptColorSchemeAtom::PptColorSchemeAtom()
355 Color PptColorSchemeAtom::GetColor( sal_uInt16 nNum ) const
357 Color aRetval;
358 if ( nNum < 8 )
360 nNum <<= 2;
361 aRetval.SetRed( aData[ nNum++ ] );
362 aRetval.SetGreen( aData[ nNum++ ] );
363 aRetval.SetBlue( aData[ nNum++ ] );
365 return aRetval;
368 SvStream& ReadPptColorSchemeAtom( SvStream& rIn, PptColorSchemeAtom& rAtom )
370 DffRecordHeader aHd;
371 ReadDffRecordHeader( rIn, aHd );
372 rIn.ReadBytes(rAtom.aData, 32);
373 aHd.SeekToEndOfRecord( rIn );
374 return rIn;
377 SvStream& ReadPptFontEntityAtom( SvStream& rIn, PptFontEntityAtom& rAtom )
379 DffRecordHeader aHd;
380 ReadDffRecordHeader( rIn, aHd );
381 sal_Unicode nTemp, cData[ 32 ];
382 rIn.ReadBytes(cData, 64);
384 sal_uInt8 lfCharset, lfPitchAndFamily;
386 rIn.ReadUChar( lfCharset )
387 .ReadUChar( rAtom.lfClipPrecision )
388 .ReadUChar( rAtom.lfQuality )
389 .ReadUChar( lfPitchAndFamily );
391 switch( lfCharset )
393 case SYMBOL_CHARSET :
394 rAtom.eCharSet = RTL_TEXTENCODING_SYMBOL;
395 break;
396 case ANSI_CHARSET :
397 rAtom.eCharSet = RTL_TEXTENCODING_MS_1252;
398 break;
400 default :
401 rAtom.eCharSet = osl_getThreadTextEncoding();
403 switch ( lfPitchAndFamily & 0xf0 )
405 case FF_ROMAN:
406 rAtom.eFamily = FAMILY_ROMAN;
407 break;
409 case FF_SWISS:
410 rAtom.eFamily = FAMILY_SWISS;
411 break;
413 case FF_MODERN:
414 rAtom.eFamily = FAMILY_MODERN;
415 break;
417 case FF_SCRIPT:
418 rAtom.eFamily = FAMILY_SCRIPT;
419 break;
421 case FF_DECORATIVE:
422 rAtom.eFamily = FAMILY_DECORATIVE;
423 break;
425 default:
426 rAtom.eFamily = FAMILY_DONTKNOW;
427 break;
430 switch ( lfPitchAndFamily & 0x0f )
432 case FIXED_PITCH:
433 rAtom.ePitch = PITCH_FIXED;
434 break;
436 case DEFAULT_PITCH:
437 case VARIABLE_PITCH:
438 default:
439 rAtom.ePitch = PITCH_VARIABLE;
440 break;
442 sal_uInt16 i;
443 for ( i = 0; i < 32; i++ )
445 nTemp = cData[ i ];
446 if ( !nTemp )
447 break;
448 #ifdef OSL_BIGENDIAN
449 cData[ i ] = ( nTemp >> 8 ) | ( nTemp << 8 );
450 #endif
452 rAtom.aName = OUString(cData, i);
453 OutputDevice* pDev = Application::GetDefaultDevice();
454 rAtom.bAvailable = pDev->IsFontAvailable( rAtom.aName );
455 aHd.SeekToEndOfRecord( rIn );
456 return rIn;
459 SvStream& ReadPptUserEditAtom( SvStream& rIn, PptUserEditAtom& rAtom )
461 sal_Int16 lastViewType = 0;
462 ReadDffRecordHeader( rIn, rAtom.aHd );
464 .ReadInt32( rAtom.nLastSlideID )
465 .ReadUInt32( rAtom.nVersion )
466 .ReadUInt32( rAtom.nOffsetLastEdit )
467 .ReadUInt32( rAtom.nOffsetPersistDirectory )
468 .ReadUInt32( rAtom.nDocumentRef )
469 .ReadUInt32( rAtom.nMaxPersistWritten )
470 .ReadInt16( lastViewType );
471 rAtom.eLastViewType = static_cast<PptViewTypeEnum>(lastViewType);
472 rAtom.aHd.SeekToEndOfRecord(rIn);
473 return rIn;
476 void PptOEPlaceholderAtom::Clear()
478 nPlacementId = 0;
479 nPlaceholderSize = 0;
480 nPlaceholderId = PptPlaceholder::NONE;
483 SvStream& ReadPptOEPlaceholderAtom( SvStream& rIn, PptOEPlaceholderAtom& rAtom )
485 rIn.ReadUInt32( rAtom.nPlacementId );
486 sal_uInt8 nTmp(0);
487 rIn.ReadUChar(nTmp);
488 rAtom.nPlaceholderId = static_cast<PptPlaceholder>(nTmp);
489 rIn.ReadUChar( rAtom.nPlaceholderSize );
490 return rIn;
493 PptSlidePersistEntry::PptSlidePersistEntry() :
494 nSlidePersistStartOffset( 0 ),
495 nSlidePersistEndOffset ( 0 ),
496 nBackgroundOffset ( 0 ),
497 nDrawingDgId ( 0xffffffff ),
498 ePageKind ( PPT_MASTERPAGE ),
499 bNotesMaster ( false ),
500 bHandoutMaster ( false ),
501 bStarDrawFiller ( false )
503 HeaderFooterOfs[ 0 ] = HeaderFooterOfs[ 1 ] = HeaderFooterOfs[ 2 ] = HeaderFooterOfs[ 3 ] = 0;
506 PptSlidePersistEntry::~PptSlidePersistEntry()
510 SdrEscherImport::SdrEscherImport( PowerPointImportParam& rParam, const OUString& rBaseURL ) :
511 SvxMSDffManager ( rParam.rDocStream, rBaseURL ),
512 nStreamLen ( 0 ),
513 rImportParam ( rParam )
517 SdrEscherImport::~SdrEscherImport()
521 const PptSlideLayoutAtom* SdrEscherImport::GetSlideLayoutAtom() const
523 return nullptr;
526 bool SdrEscherImport::ReadString( OUString& rStr ) const
528 bool bRet = false;
529 DffRecordHeader aStrHd;
530 ReadDffRecordHeader( rStCtrl, aStrHd );
531 if (aStrHd.nRecType == PPT_PST_TextBytesAtom
532 || aStrHd.nRecType == PPT_PST_TextCharsAtom
533 || aStrHd.nRecType == PPT_PST_CString)
535 bool bUniCode =
536 (aStrHd.nRecType == PPT_PST_TextCharsAtom
537 || aStrHd.nRecType == PPT_PST_CString);
538 sal_uLong nBytes = aStrHd.nRecLen;
539 rStr = MSDFFReadZString( rStCtrl, nBytes, bUniCode );
540 bRet = aStrHd.SeekToEndOfRecord( rStCtrl );
542 else
543 aStrHd.SeekToBegOfRecord( rStCtrl );
544 return bRet;
547 bool SdrEscherImport::GetColorFromPalette(sal_uInt16 /*nNum*/, Color& /*rColor*/) const
549 return false;
552 bool SdrEscherImport::SeekToShape( SvStream& /*rSt*/, SvxMSDffClientData* /*pClientData*/, sal_uInt32 /*nId*/) const
554 return false;
557 const PptFontEntityAtom* SdrEscherImport::GetFontEnityAtom( sal_uInt32 nNum ) const
559 if (m_xFonts && nNum < m_xFonts->size())
560 return &(*m_xFonts)[ nNum ];
561 return nullptr;
564 SdrObject* SdrEscherImport::ReadObjText( PPTTextObj* /*pTextObj*/, SdrObject* pObj, SdPageCapsule /*pPage*/) const
566 return pObj;
569 void SdrEscherImport::ProcessClientAnchor2( SvStream& rSt, DffRecordHeader& rHd, DffObjData& rObj )
571 sal_Int32 l, t, r, b;
572 if ( rHd.nRecLen == 16 )
574 rSt.ReadInt32( l ).ReadInt32( t ).ReadInt32( r ).ReadInt32( b );
576 else
578 sal_Int16 ls, ts, rs, bs;
579 rSt.ReadInt16( ts ).ReadInt16( ls ).ReadInt16( rs ).ReadInt16( bs ); // the order of coordinates is a bit strange...
580 l = ls;
581 t = ts;
582 r = rs;
583 b = bs;
585 if (!rSt.good())
587 SAL_WARN("filter.ms", "ProcessClientAnchor2: short read");
588 return;
590 Scale( l );
591 Scale( t );
592 Scale( r );
593 Scale( b );
594 rObj.aChildAnchor = tools::Rectangle( l, t, r, b );
595 rObj.bChildAnchor = true;
598 void SdrEscherImport::RecolorGraphic( SvStream& rSt, sal_uInt32 nRecLen, Graphic& rGraphic )
600 if ( rGraphic.GetType() != GraphicType::GdiMetafile )
601 return;
603 sal_uInt16 nX, nGlobalColorsCount, nFillColorsCount;
605 rSt.ReadUInt16( nX )
606 .ReadUInt16( nGlobalColorsCount )
607 .ReadUInt16( nFillColorsCount )
608 .ReadUInt16( nX )
609 .ReadUInt16( nX )
610 .ReadUInt16( nX );
612 if ( ( nGlobalColorsCount > 64 ) || ( nFillColorsCount > 64 ) )
613 return;
615 if ( static_cast<sal_uInt32>( ( nGlobalColorsCount + nFillColorsCount ) * 44 + 12 ) != nRecLen )
616 return;
618 sal_uInt32 OriginalGlobalColors[ 64 ];
619 sal_uInt32 NewGlobalColors[ 64 ];
621 sal_uInt32 i, j, nGlobalColorsChanged, nFillColorsChanged;
622 nGlobalColorsChanged = nFillColorsChanged = 0;
624 sal_uInt32* pCurrentOriginal = OriginalGlobalColors;
625 sal_uInt32* pCurrentNew = NewGlobalColors;
626 sal_uInt32* pCount = &nGlobalColorsChanged;
627 i = nGlobalColorsCount;
629 for ( j = 0; j < 2; j++ )
631 for ( ; i > 0; i-- )
633 sal_uInt64 nPos = rSt.Tell();
634 sal_uInt16 nChanged;
635 rSt.ReadUInt16( nChanged );
636 if ( nChanged & 1 )
638 sal_uInt8 nDummy, nRed, nGreen, nBlue;
639 sal_uInt32 nColor = 0;
640 sal_uInt32 nIndex;
641 rSt.ReadUChar( nDummy )
642 .ReadUChar( nRed )
643 .ReadUChar( nDummy )
644 .ReadUChar( nGreen )
645 .ReadUChar( nDummy )
646 .ReadUChar( nBlue )
647 .ReadUInt32( nIndex );
649 if ( nIndex < 8 )
651 Color aColor = MSO_CLR_ToColor( nIndex << 24 );
652 nRed = aColor.GetRed();
653 nGreen = aColor.GetGreen();
654 nBlue = aColor.GetBlue();
656 nColor = nRed | ( nGreen << 8 ) | ( nBlue << 16 );
657 *pCurrentNew++ = nColor;
658 rSt.ReadUChar( nDummy )
659 .ReadUChar( nRed )
660 .ReadUChar( nDummy )
661 .ReadUChar( nGreen )
662 .ReadUChar( nDummy )
663 .ReadUChar( nBlue );
664 nColor = nRed | ( nGreen << 8 ) | ( nBlue << 16 );
665 *pCurrentOriginal++ = nColor;
666 (*pCount)++;
668 rSt.Seek( nPos + 44 );
670 pCount = &nFillColorsChanged;
671 i = nFillColorsCount;
673 if ( !(nGlobalColorsChanged || nFillColorsChanged) )
674 return;
676 std::unique_ptr<Color[]> pSearchColors(new Color[ nGlobalColorsChanged ]);
677 std::unique_ptr<Color[]> pReplaceColors(new Color[ nGlobalColorsChanged ]);
679 for ( j = 0; j < nGlobalColorsChanged; j++ )
681 sal_uInt32 nSearch = OriginalGlobalColors[ j ];
682 sal_uInt32 nReplace = NewGlobalColors[ j ];
684 pSearchColors[ j ].SetRed( static_cast<sal_uInt8>(nSearch) );
685 pSearchColors[ j ].SetGreen( static_cast<sal_uInt8>( nSearch >> 8 ) );
686 pSearchColors[ j ].SetBlue( static_cast<sal_uInt8>( nSearch >> 16 ) );
688 pReplaceColors[ j ].SetRed( static_cast<sal_uInt8>(nReplace) );
689 pReplaceColors[ j ].SetGreen( static_cast<sal_uInt8>( nReplace >> 8 ) );
690 pReplaceColors[ j ].SetBlue( static_cast<sal_uInt8>( nReplace >> 16 ) );
692 GDIMetaFile aGdiMetaFile( rGraphic.GetGDIMetaFile() );
693 aGdiMetaFile.ReplaceColors( pSearchColors.get(), pReplaceColors.get(),
694 nGlobalColorsChanged );
695 rGraphic = aGdiMetaFile;
698 sal_uLong DffPropSet::SanitizeEndPos(SvStream &rIn, sal_uLong nEndRecPos)
700 auto nStreamLen = rIn.Tell() + rIn.remainingSize();
701 if (nEndRecPos > nStreamLen)
703 SAL_WARN("filter.ms", "Parsing error: " << nStreamLen <<
704 " max end pos, but " << nEndRecPos << " claimed, truncating");
705 nEndRecPos = nStreamLen;
707 return nEndRecPos;
710 void ProcessData::NotifyFreeObj(SdrObject* pObj)
712 if (rPersistEntry.xSolverContainer)
714 for (auto & pPtr : rPersistEntry.xSolverContainer->aCList)
716 if (pPtr->pAObj == pObj)
717 pPtr->pAObj = nullptr;
718 if (pPtr->pBObj == pObj)
719 pPtr->pBObj = nullptr;
720 if (pPtr->pCObj == pObj)
721 pPtr->pCObj = nullptr;
726 /* ProcessObject is called from ImplSdPPTImport::ProcessObj to handle all application specific things,
727 such as the import of text, animation effects, header footer and placeholder.
729 The parameter pOriginalObj is the object as it was imported by our general escher import, it must either
730 be deleted or it can be returned to be inserted into the sdr page.
732 rtl::Reference<SdrObject> SdrEscherImport::ProcessObj( SvStream& rSt, DffObjData& rObjData, SvxMSDffClientData& rClientData, tools::Rectangle& rTextRect, SdrObject* pOriginalObj )
734 if ( dynamic_cast<const SdrObjCustomShape* >(pOriginalObj) != nullptr )
735 pOriginalObj->SetMergedItem( SdrTextFixedCellHeightItem( true ) );
737 // we are initializing our return value with the object that was imported by our escher import
738 rtl::Reference<SdrObject> pRet = pOriginalObj;
740 ProcessData& rData = static_cast<ProcessData&>(rClientData);
741 PptSlidePersistEntry& rPersistEntry = rData.rPersistEntry;
743 if ( ! (rObjData.nSpFlags & ShapeFlag::Group) ) // sj: #114758# ...
745 PptOEPlaceholderAtom aPlaceholderAtom;
747 if ( maShapeRecords.SeekToContent( rSt, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) )
749 sal_Int16 nHeaderFooterInstance = -1;
750 DffRecordHeader aClientDataHd;
751 auto nEndRecPos = SanitizeEndPos(rSt, maShapeRecords.Current()->GetRecEndFilePos());
752 while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nEndRecPos ) )
754 ReadDffRecordHeader( rSt, aClientDataHd );
755 switch ( aClientDataHd.nRecType )
757 // importing header/footer object from master page
758 case PPT_PST_OEPlaceholderAtom :
760 ReadPptOEPlaceholderAtom( rSt, aPlaceholderAtom );
761 if ( nHeaderFooterInstance == -1 )
763 switch ( aPlaceholderAtom.nPlaceholderId )
765 case PptPlaceholder::MASTERSLIDENUMBER : nHeaderFooterInstance++;
766 [[fallthrough]];
767 case PptPlaceholder::MASTERFOOTER : nHeaderFooterInstance++;
768 [[fallthrough]];
769 case PptPlaceholder::MASTERHEADER : nHeaderFooterInstance++;
770 [[fallthrough]];
771 case PptPlaceholder::MASTERDATE : nHeaderFooterInstance++; break;
772 default: break;
775 if ( ! ( nHeaderFooterInstance & 0xfffc ) ) // is this a valid instance ( 0->3 )
776 rPersistEntry.HeaderFooterOfs[ nHeaderFooterInstance ] = rObjData.rSpHd.GetRecBegFilePos();
779 break;
781 case PPT_PST_RecolorInfoAtom :
783 if ( auto pSdrGrafObj = dynamic_cast<SdrGrafObj* >(pRet.get()) )
784 if ( pSdrGrafObj->HasGDIMetaFile() )
786 Graphic aGraphic( pSdrGrafObj->GetGraphic() );
787 RecolorGraphic( rSt, aClientDataHd.nRecLen, aGraphic );
788 pSdrGrafObj->SetGraphic( aGraphic );
791 break;
793 if (!aClientDataHd.SeekToEndOfRecord(rSt))
794 break;
797 if ( ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::NOTESSLIDEIMAGE ) && !rPersistEntry.bNotesMaster )
799 sal_uInt16 nPageNum = pSdrModel->GetPageCount();
800 if ( nPageNum > 0 )
801 nPageNum--;
803 // replacing the object which we will return with a SdrPageObj
804 pRet = new SdrPageObj(
805 *pSdrModel,
806 rObjData.aBoundRect,
807 pSdrModel->GetPage(nPageNum - 1));
809 else
811 // try to load some ppt text
812 PPTTextObj aTextObj( rSt, static_cast<SdrPowerPointImport&>(*this), rPersistEntry, &rObjData );
813 if ( aTextObj.Count() || aTextObj.GetOEPlaceHolderAtom() )
815 bool bVerticalText = false;
816 // and if the text object is not empty, it must be applied to pRet, the object we
817 // initially got from our escher import
818 Degree100 nTextRotationAngle(0);
819 if ( IsProperty( DFF_Prop_txflTextFlow ) )
821 auto eTextFlow = GetPropertyValue(DFF_Prop_txflTextFlow, 0) & 0xFFFF;
822 switch( eTextFlow )
824 case mso_txflBtoT : // Bottom to Top non-@
825 nTextRotationAngle += 9000_deg100;
826 break;
827 case mso_txflTtoBA : /* #68110# */ // Top to Bottom @-font
828 case mso_txflTtoBN : // Top to Bottom non-@
829 case mso_txflVertN : // Vertical, non-@, top to bottom
830 bVerticalText = !bVerticalText; // nTextRotationAngle += 27000;
831 break;
832 // case mso_txflHorzN : // Horizontal non-@, normal
833 // case mso_txflHorzA : // Horizontal @-font, normal
834 default: break;
837 sal_Int32 nFontDirection = GetPropertyValue( DFF_Prop_cdirFont, mso_cdir0 );
838 if ( ( nFontDirection == 1 ) || ( nFontDirection == 3 ) )
840 bVerticalText = !bVerticalText;
842 const bool bFail = o3tl::checked_multiply<sal_Int32>(nFontDirection, 9000, nFontDirection);
843 if (!bFail)
844 nTextRotationAngle -= Degree100(nFontDirection);
845 else
846 SAL_WARN("filter.ms", "Parsing error: bad fontdirection: " << nFontDirection);
847 aTextObj.SetVertical( bVerticalText );
848 if ( pRet )
850 bool bDeleteSource = aTextObj.GetOEPlaceHolderAtom().has_value();
851 if ( bDeleteSource && dynamic_cast<const SdrGrafObj* >(pRet.get()) == nullptr // we are not allowed to get
852 && dynamic_cast<const SdrObjGroup* >(pRet.get()) == nullptr // grouped placeholder objects
853 && dynamic_cast<const SdrOle2Obj* >(pRet.get()) == nullptr )
855 pRet = nullptr;
858 sal_uInt32 nTextFlags = aTextObj.GetTextFlags();
859 sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 25 * 3600 ); // 0.25 cm (emu)
860 sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 25 * 3600 ); // 0.25 cm (emu)
861 sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 13 * 3600 ); // 0.13 cm (emu)
862 sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 13 * 3600 );
863 ScaleEmu( nTextLeft );
864 ScaleEmu( nTextRight );
865 ScaleEmu( nTextTop );
866 ScaleEmu( nTextBottom );
868 sal_Int32 nMinFrameWidth = 0;
869 sal_Int32 nMinFrameHeight = 0;
870 bool bAutoGrowWidth, bAutoGrowHeight;
872 SdrTextVertAdjust eTVA;
873 SdrTextHorzAdjust eTHA;
875 nTextFlags &= PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT
876 | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK;
878 if ( bVerticalText )
880 eTVA = SDRTEXTVERTADJUST_BLOCK;
881 eTHA = SDRTEXTHORZADJUST_CENTER;
883 // read text anchor
884 auto eTextAnchor = GetPropertyValue(DFF_Prop_anchorText, mso_anchorTop);
886 switch( eTextAnchor )
888 case mso_anchorTop:
889 case mso_anchorTopCentered:
890 case mso_anchorTopBaseline:
891 case mso_anchorTopCenteredBaseline:
892 eTHA = SDRTEXTHORZADJUST_RIGHT;
893 break;
895 case mso_anchorMiddle :
896 case mso_anchorMiddleCentered:
897 eTHA = SDRTEXTHORZADJUST_CENTER;
898 break;
900 case mso_anchorBottom:
901 case mso_anchorBottomCentered:
902 case mso_anchorBottomBaseline:
903 case mso_anchorBottomCenteredBaseline:
904 eTHA = SDRTEXTHORZADJUST_LEFT;
905 break;
907 switch ( eTextAnchor )
909 case mso_anchorTopCentered :
910 case mso_anchorMiddleCentered :
911 case mso_anchorBottomCentered :
912 case mso_anchorTopCenteredBaseline:
913 case mso_anchorBottomCenteredBaseline:
915 // check if it is sensible to use the centered alignment
916 const sal_uInt32 nMask = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK;
917 switch (nTextFlags & nMask)
919 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT:
920 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER:
921 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT:
922 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK:
923 eTVA = SDRTEXTVERTADJUST_CENTER; // If the textobject has only one type of alignment, then the text has not to be displayed using the full width;
924 break;
926 break;
928 default:
929 break;
931 nMinFrameWidth = rTextRect.GetWidth() - ( nTextLeft + nTextRight );
933 else
935 eTVA = SDRTEXTVERTADJUST_CENTER;
936 eTHA = SDRTEXTHORZADJUST_BLOCK;
938 // read text anchor
939 auto eTextAnchor = GetPropertyValue(DFF_Prop_anchorText, mso_anchorTop);
941 switch( eTextAnchor )
943 case mso_anchorTop:
944 case mso_anchorTopCentered:
945 case mso_anchorTopBaseline:
946 case mso_anchorTopCenteredBaseline:
947 eTVA = SDRTEXTVERTADJUST_TOP;
948 break;
950 case mso_anchorMiddle :
951 case mso_anchorMiddleCentered:
952 eTVA = SDRTEXTVERTADJUST_CENTER;
953 break;
955 case mso_anchorBottom:
956 case mso_anchorBottomCentered:
957 case mso_anchorBottomBaseline:
958 case mso_anchorBottomCenteredBaseline:
959 eTVA = SDRTEXTVERTADJUST_BOTTOM;
960 break;
962 switch ( eTextAnchor )
964 case mso_anchorTopCentered :
965 case mso_anchorMiddleCentered :
966 case mso_anchorBottomCentered :
967 case mso_anchorTopCenteredBaseline:
968 case mso_anchorBottomCenteredBaseline:
970 // check if it is sensible to use the centered alignment
971 const sal_uInt32 nMask = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK;
972 switch (nTextFlags & nMask)
974 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT:
975 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER:
976 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT:
977 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK:
978 eTHA = SDRTEXTHORZADJUST_CENTER; // If the textobject has only one type of alignment, then the text has not to be displayed using the full width;
979 break;
981 break;
983 default:
984 break;
986 nMinFrameHeight = rTextRect.GetHeight() - ( nTextTop + nTextBottom );
989 SdrObjKind eTextKind = SdrObjKind::Rectangle;
990 if ( ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::NOTESSLIDEIMAGE )
991 || ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::MASTERNOTESSLIDEIMAGE ) )
993 aTextObj.SetInstance( TSS_Type::Notes );
994 eTextKind = SdrObjKind::TitleText;
996 else if ( ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::MASTERNOTESBODYIMAGE )
997 || ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::NOTESBODY ) )
999 aTextObj.SetInstance( TSS_Type::Notes );
1000 eTextKind = SdrObjKind::Text;
1003 TSS_Type nDestinationInstance = aTextObj.GetInstance();
1004 if ( rPersistEntry.ePageKind == PPT_MASTERPAGE )
1006 if ( !rPersistEntry.pPresentationObjects )
1008 rPersistEntry.pPresentationObjects.reset( new sal_uInt32[ PPT_STYLESHEETENTRIES ] );
1009 memset( rPersistEntry.pPresentationObjects.get(), 0, PPT_STYLESHEETENTRIES * 4 );
1011 if ( !rPersistEntry.pPresentationObjects[ static_cast<int>(nDestinationInstance) ] )
1012 rPersistEntry.pPresentationObjects[ static_cast<int>(nDestinationInstance) ] = rObjData.rSpHd.GetRecBegFilePos();
1014 switch ( nDestinationInstance )
1016 case TSS_Type::PageTitle :
1017 case TSS_Type::Title :
1019 if ( GetSlideLayoutAtom()->eLayout == PptSlideLayout::TITLEMASTERSLIDE )
1020 nDestinationInstance = TSS_Type::Title;
1021 else
1022 nDestinationInstance = TSS_Type::PageTitle;
1024 break;
1025 case TSS_Type::Body :
1026 case TSS_Type::HalfBody :
1027 case TSS_Type::QuarterBody :
1028 nDestinationInstance = TSS_Type::Body;
1029 break;
1030 default: break;
1032 aTextObj.SetDestinationInstance( nDestinationInstance );
1034 bool bAutoFit = false; // auto-scale text into shape box
1035 switch ( aTextObj.GetInstance() )
1037 case TSS_Type::PageTitle :
1038 case TSS_Type::Title : eTextKind = SdrObjKind::TitleText; break;
1039 case TSS_Type::Subtitle : eTextKind = SdrObjKind::Text; break;
1040 case TSS_Type::Body :
1041 case TSS_Type::HalfBody :
1042 case TSS_Type::QuarterBody : eTextKind = SdrObjKind::OutlineText; bAutoFit = true; break;
1043 default: break;
1045 if ( aTextObj.GetDestinationInstance() != TSS_Type::TextInShape )
1047 if ( !aTextObj.GetOEPlaceHolderAtom() || aTextObj.GetOEPlaceHolderAtom()->nPlaceholderId == PptPlaceholder::NONE )
1049 aTextObj.SetDestinationInstance( TSS_Type::TextInShape );
1050 eTextKind = SdrObjKind::Rectangle;
1053 rtl::Reference<SdrObject> pTObj;
1054 bool bWordWrap = GetPropertyValue(DFF_Prop_WrapText, mso_wrapSquare) != mso_wrapNone;
1055 bool bFitShapeToText = ( GetPropertyValue( DFF_Prop_FitTextToShape, 0 ) & 2 ) != 0;
1057 if ( dynamic_cast<const SdrObjCustomShape* >(pRet.get()) != nullptr && ( eTextKind == SdrObjKind::Rectangle ) )
1059 bAutoGrowHeight = bFitShapeToText;
1060 bAutoGrowWidth = !bWordWrap;
1061 pTObj = pRet;
1062 pRet = nullptr;
1064 else
1066 if ( dynamic_cast<const SdrObjCustomShape* >(pRet.get()) != nullptr )
1068 pRet = nullptr;
1070 pTObj = new SdrRectObj(
1071 *pSdrModel,
1072 eTextKind != SdrObjKind::Rectangle ? eTextKind : SdrObjKind::Text);
1073 SfxItemSet aSet( pSdrModel->GetItemPool() );
1074 if ( !pRet )
1075 ApplyAttributes( rSt, aSet, rObjData );
1076 pTObj->SetMergedItemSet( aSet );
1077 if ( pRet )
1079 pTObj->SetMergedItem( XLineStyleItem( drawing::LineStyle_NONE ) );
1080 pTObj->SetMergedItem( XFillStyleItem( drawing::FillStyle_NONE ) );
1082 if ( bVerticalText )
1084 bAutoGrowWidth = bFitShapeToText;
1085 bAutoGrowHeight = false;
1087 else
1089 bAutoGrowWidth = false;
1091 // #119885# re-activating bFitShapeToText here, could not find deeper explanations
1092 // for it (it was from 2005). Keeping the old comment here for reference
1093 // old comment: // bFitShapeToText; can't be used, because we cut the text if it is too height,
1094 bAutoGrowHeight = bFitShapeToText;
1097 pTObj->SetMergedItem( SvxFrameDirectionItem( bVerticalText ? SvxFrameDirection::Vertical_RL_TB : SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ) );
1099 //Autofit text only if there is no auto grow height and width
1100 //See fdo#41245
1101 if (bAutoFit && !bAutoGrowHeight && !bAutoGrowWidth)
1103 pTObj->SetMergedItem( SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_AUTOFIT) );
1106 if ( dynamic_cast<const SdrObjCustomShape* >(pTObj.get()) == nullptr )
1108 pTObj->SetMergedItem( makeSdrTextAutoGrowWidthItem( bAutoGrowWidth ) );
1109 pTObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( bAutoGrowHeight ) );
1111 else
1113 pTObj->SetMergedItem( makeSdrTextWordWrapItem( bWordWrap ) );
1114 pTObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( bFitShapeToText ) );
1117 pTObj->SetMergedItem( SdrTextVertAdjustItem( eTVA ) );
1118 pTObj->SetMergedItem( SdrTextHorzAdjustItem( eTHA ) );
1120 if ( nMinFrameHeight < 0 )
1121 nMinFrameHeight = 0;
1122 if ( dynamic_cast<const SdrObjCustomShape* >(pTObj.get()) == nullptr )
1123 pTObj->SetMergedItem( makeSdrTextMinFrameHeightItem( nMinFrameHeight ) );
1125 if ( nMinFrameWidth < 0 )
1126 nMinFrameWidth = 0;
1127 if ( dynamic_cast<const SdrObjCustomShape* >(pTObj.get()) == nullptr )
1128 pTObj->SetMergedItem( makeSdrTextMinFrameWidthItem( nMinFrameWidth ) );
1130 // set margins at the borders of the textbox
1131 pTObj->SetMergedItem( makeSdrTextLeftDistItem( nTextLeft ) );
1132 pTObj->SetMergedItem( makeSdrTextRightDistItem( nTextRight ) );
1133 pTObj->SetMergedItem( makeSdrTextUpperDistItem( nTextTop ) );
1134 pTObj->SetMergedItem( makeSdrTextLowerDistItem( nTextBottom ) );
1135 pTObj->SetMergedItem( SdrTextFixedCellHeightItem( true ) );
1137 if ( dynamic_cast<const SdrObjCustomShape* >(pTObj.get()) == nullptr )
1138 pTObj->SetSnapRect( rTextRect );
1139 pTObj = ReadObjText( &aTextObj, pTObj.get(), rData.pPage );
1141 if ( pTObj )
1143 /* check if our new snaprect makes trouble,
1144 because we do not display the ADJUST_BLOCK
1145 properly if the textsize is bigger than the
1146 snaprect of the object. Then we will use
1147 ADJUST_CENTER instead of ADJUST_BLOCK.
1149 if ( dynamic_cast<const SdrObjCustomShape* >(pTObj.get()) == nullptr && !bFitShapeToText && !bWordWrap )
1151 SdrTextObj* pText = DynCastSdrTextObj( pTObj.get() );
1152 if ( pText )
1154 if ( bVerticalText )
1156 if ( eTVA == SDRTEXTVERTADJUST_BLOCK )
1158 Size aTextSize( pText->GetTextSize() );
1159 aTextSize.AdjustWidth(nTextLeft + nTextRight );
1160 aTextSize.AdjustHeight(nTextTop + nTextBottom );
1161 if ( rTextRect.GetHeight() < aTextSize.Height() )
1162 pTObj->SetMergedItem( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) );
1165 else
1167 if ( eTHA == SDRTEXTHORZADJUST_BLOCK )
1169 Size aTextSize( pText->GetTextSize() );
1170 aTextSize.AdjustWidth(nTextLeft + nTextRight );
1171 aTextSize.AdjustHeight(nTextTop + nTextBottom );
1172 if ( rTextRect.GetWidth() < aTextSize.Width() )
1173 pTObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_CENTER ) );
1178 // rotate text with shape?
1179 Degree100 nAngle = ( rObjData.nSpFlags & ShapeFlag::FlipV ) ? -mnFix16Angle : mnFix16Angle; // #72116# vertical flip -> rotate by using the other way
1180 nAngle += nTextRotationAngle;
1182 if ( dynamic_cast< const SdrObjCustomShape* >(pTObj.get()) == nullptr )
1184 if ( rObjData.nSpFlags & ShapeFlag::FlipV )
1186 pTObj->Rotate( rTextRect.Center(), 18000_deg100, 0.0, -1.0 );
1188 if ( rObjData.nSpFlags & ShapeFlag::FlipH )
1189 nAngle = 36000_deg100 - nAngle;
1190 if ( nAngle )
1191 pTObj->NbcRotate( rObjData.aBoundRect.Center(), nAngle );
1193 if ( pRet )
1195 rtl::Reference<SdrObject> pGroup = new SdrObjGroup(*pSdrModel);
1196 pGroup->GetSubList()->NbcInsertObject( pRet.get() );
1197 pGroup->GetSubList()->NbcInsertObject( pTObj.get() );
1198 pRet = pGroup;
1200 else
1201 pRet = pTObj.get();
1206 else
1208 if ( maShapeRecords.SeekToContent( rSt, DFF_msofbtUDefProp, SEEK_FROM_CURRENT_AND_RESTART ) )
1210 maShapeRecords.Current()->SeekToBegOfRecord( rSt );
1211 DffPropertyReader aSecPropSet( *this );
1212 aSecPropSet.ReadPropSet( rSt, &rClientData );
1213 sal_Int32 nTableProperties = aSecPropSet.GetPropertyValue( DFF_Prop_tableProperties, 0 );
1214 if ( nTableProperties & 3 )
1216 if ( aSecPropSet.SeekToContent( DFF_Prop_tableRowProperties, rSt ) )
1218 sal_Int16 i, nReadRowCount = 0;
1219 rSt.ReadInt16( nReadRowCount ).ReadInt16( i ).ReadInt16( i );
1220 if (nReadRowCount > 0)
1222 const size_t nMinRecordSize = 4;
1223 const size_t nMaxRecords = rSt.remainingSize() / nMinRecordSize;
1225 auto nRowCount = o3tl::make_unsigned(nReadRowCount);
1226 if (nRowCount > nMaxRecords)
1228 SAL_WARN("filter.ms", "Parsing error: " << nMaxRecords <<
1229 " max possible entries, but " << nRowCount << " claimed, truncating");
1230 nRowCount = nMaxRecords;
1232 if (nRowCount > 0)
1234 std::unique_ptr<sal_uInt32[]> pTableArry(new sal_uInt32[ nRowCount + 2 ]);
1235 pTableArry[ 0 ] = nTableProperties;
1236 pTableArry[ 1 ] = nRowCount;
1237 for (decltype(nRowCount) nRow = 0; nRow < nRowCount; ++nRow)
1238 rSt.ReadUInt32(pTableArry[nRow + 2]);
1239 rData.pTableRowProperties = std::move(pTableArry);
1246 if ( pRet ) // sj: #i38501#, and taking care of connections to group objects
1248 if ( rObjData.nSpFlags & ShapeFlag::Background )
1250 pRet->NbcSetSnapRect( tools::Rectangle( Point(), rData.pPage.page->GetSize() ) ); // set size
1252 if (rPersistEntry.xSolverContainer)
1254 for (auto & pPtr : rPersistEntry.xSolverContainer->aCList)
1256 if ( rObjData.nShapeId == pPtr->nShapeC )
1257 pPtr->pCObj = pRet.get();
1258 else
1260 SdrObject* pConnectObj = pRet.get();
1261 if ( pOriginalObj && dynamic_cast< const SdrObjGroup* >(pRet.get()) != nullptr )
1262 { /* check if the original object from the escherimport is part of the group object,
1263 if this is the case, we will use the original object to connect to */
1264 SdrObjListIter aIter( *pRet, SdrIterMode::DeepWithGroups );
1265 while( aIter.IsMore() )
1267 SdrObject* pPartObj = aIter.Next();
1268 if ( pPartObj == pOriginalObj )
1270 pConnectObj = pPartObj;
1271 break;
1275 if ( rObjData.nShapeId == pPtr->nShapeA )
1277 pPtr->pAObj = pConnectObj;
1278 pPtr->nSpFlagsA = rObjData.nSpFlags;
1280 if ( rObjData.nShapeId == pPtr->nShapeB )
1282 pPtr->pBObj = pConnectObj;
1283 pPtr->nSpFlagsB = rObjData.nSpFlags;
1288 if ( rPersistEntry.ePageKind == PPT_MASTERPAGE )
1289 { // maybe the escher clusterlist is not correct, but we have to got the right page by using the
1290 // spMaster property, so we are patching the table
1291 if ( rPersistEntry.nDrawingDgId != 0xffffffff )
1293 sal_uInt32 nSec = ( rObjData.nShapeId >> 10 ) - 1;
1294 if ( !maFidcls.empty() && ( nSec < mnIdClusters ) )
1295 maFidcls[ nSec ].dgid = rPersistEntry.nDrawingDgId; // insert the correct drawing id;
1299 return pRet;
1302 SdrPowerPointImport::SdrPowerPointImport( PowerPointImportParam& rParam, const OUString& rBaseURL ) :
1303 SdrEscherImport ( rParam, rBaseURL ),
1304 m_bOk ( rStCtrl.GetErrorCode() == ERRCODE_NONE ),
1305 m_nPersistPtrCnt ( 0 ),
1306 m_pDefaultSheet ( nullptr ),
1307 m_nCurrentPageNum ( 0 ),
1308 m_nDocStreamPos ( 0 ),
1309 m_nPageColorsNum ( 0xFFFF ),
1310 m_ePageColorsKind ( PPT_MASTERPAGE ),
1311 m_eCurrentPageKind ( PPT_MASTERPAGE )
1313 if ( m_bOk )
1315 nStreamLen = rStCtrl.TellEnd();
1317 // try to allocate the UserEditAtom via CurrentUserAtom
1318 sal_uInt32 nCurrentUserEdit = rParam.aCurrentUserAtom.nCurrentUserEdit;
1319 if (nCurrentUserEdit && checkSeek(rStCtrl, nCurrentUserEdit))
1321 ReadPptUserEditAtom( rStCtrl, m_aUserEditAtom );
1323 if ( !m_aUserEditAtom.nOffsetPersistDirectory )
1324 { // if there is no UserEditAtom try to search the last one
1326 rStCtrl.Seek( 0 );
1327 DffRecordManager aPptRecManager; // contains all first level container and atoms
1328 aPptRecManager.Consume( rStCtrl, nStreamLen );
1329 DffRecordHeader* pHd;
1330 for ( pHd = aPptRecManager.Last(); pHd; pHd = aPptRecManager.Prev() )
1332 if ( pHd->nRecType == PPT_PST_UserEditAtom )
1334 pHd->SeekToBegOfRecord( rStCtrl );
1335 ReadPptUserEditAtom( rStCtrl, m_aUserEditAtom );
1336 break;
1339 if ( !pHd )
1340 m_bOk = false;
1343 if ( rStCtrl.GetError() != ERRCODE_NONE )
1344 m_bOk = false;
1346 if ( m_bOk )
1348 m_nPersistPtrCnt = m_aUserEditAtom.nMaxPersistWritten + 1;
1349 if ( ( m_nPersistPtrCnt >> 2 ) > nStreamLen ) // sj: at least m_nPersistPtrCnt is not allowed to be greater than filesize
1350 m_bOk = false; // (it should not be greater than the PPT_PST_PersistPtrIncrementalBlock, but
1351 // we are reading this block later, so we do not have access yet)
1353 if ( m_bOk && ( m_nPersistPtrCnt < ( SAL_MAX_UINT32 / sizeof( sal_uInt32 ) ) -1 ) )
1354 m_pPersistPtr.reset( new (std::nothrow) sal_uInt32[ m_nPersistPtrCnt + 1 ] );
1355 if ( !m_pPersistPtr )
1356 m_bOk = false;
1357 if ( m_bOk )
1359 memset( m_pPersistPtr.get(), 0x00, (m_nPersistPtrCnt+1) * sizeof(sal_uInt32) );
1361 // SJ: new search mechanism from bottom to top (Issue 21122)
1362 PptUserEditAtom aCurrentEditAtom( m_aUserEditAtom );
1363 sal_uInt32 nCurrentEditAtomStrmPos = aCurrentEditAtom.aHd.GetRecEndFilePos();
1364 while( nCurrentEditAtomStrmPos )
1366 sal_uInt32 nPersistIncPos = aCurrentEditAtom.nOffsetPersistDirectory;
1367 if (nPersistIncPos && checkSeek(rStCtrl, nPersistIncPos))
1369 DffRecordHeader aPersistHd;
1370 ReadDffRecordHeader( rStCtrl, aPersistHd );
1371 if ( aPersistHd.nRecType == PPT_PST_PersistPtrIncrementalBlock )
1373 sal_uLong nPibLen = aPersistHd.GetRecEndFilePos();
1374 while (m_bOk && rStCtrl.good() && (rStCtrl.Tell() < nPibLen))
1376 sal_uInt32 nOfs(0);
1377 rStCtrl.ReadUInt32( nOfs );
1378 sal_uInt32 nCnt = nOfs;
1379 nOfs &= 0x000FFFFF;
1380 nCnt >>= 20;
1381 while (m_bOk && rStCtrl.good() && (nCnt > 0) && (nOfs <= m_nPersistPtrCnt))
1383 sal_uInt32 nPt(0);
1384 rStCtrl.ReadUInt32( nPt );
1385 if ( !m_pPersistPtr[ nOfs ] )
1387 m_pPersistPtr[ nOfs ] = nPt;
1388 if ( m_pPersistPtr[ nOfs ] > nStreamLen )
1390 m_bOk = false;
1391 OSL_FAIL("SdrPowerPointImport::Ctor(): Invalid Entry in Persist-Directory!");
1394 nCnt--;
1395 nOfs++;
1397 if ( m_bOk && nCnt > 0 )
1399 OSL_FAIL("SdrPowerPointImport::Ctor(): Not all entries of Persist-Directory read!");
1400 m_bOk = false;
1405 nCurrentEditAtomStrmPos = aCurrentEditAtom.nOffsetLastEdit < nCurrentEditAtomStrmPos ? aCurrentEditAtom.nOffsetLastEdit : 0;
1406 if (nCurrentEditAtomStrmPos && checkSeek(rStCtrl, nCurrentEditAtomStrmPos))
1408 ReadPptUserEditAtom( rStCtrl, aCurrentEditAtom );
1413 if ( rStCtrl.GetError() != ERRCODE_NONE )
1414 m_bOk = false;
1415 if ( m_bOk )
1416 { // check Document PersistEntry
1417 m_nDocStreamPos = m_aUserEditAtom.nDocumentRef;
1418 if ( m_nDocStreamPos > m_nPersistPtrCnt )
1420 OSL_FAIL("SdrPowerPointImport::Ctor(): m_aUserEditAtom.nDocumentRef invalid!");
1421 m_bOk = false;
1424 if ( m_bOk )
1425 { // check Document FilePos
1426 m_nDocStreamPos = m_pPersistPtr[ m_nDocStreamPos ];
1427 if ( m_nDocStreamPos >= nStreamLen )
1429 OSL_FAIL("SdrPowerPointImport::Ctor(): m_nDocStreamPos >= nStreamLen!");
1430 m_bOk = false;
1433 if ( m_bOk )
1435 rStCtrl.Seek( m_nDocStreamPos );
1436 aDocRecManager.Consume( rStCtrl );
1438 DffRecordHeader aDocHd;
1439 ReadDffRecordHeader( rStCtrl, aDocHd );
1440 // read DocumentAtom
1441 DffRecordHeader aDocAtomHd;
1442 ReadDffRecordHeader( rStCtrl, aDocAtomHd );
1443 if ( aDocHd.nRecType == PPT_PST_Document && aDocAtomHd.nRecType == PPT_PST_DocumentAtom )
1445 aDocAtomHd.SeekToBegOfRecord( rStCtrl );
1446 ReadPptDocumentAtom( rStCtrl, aDocAtom );
1448 else
1449 m_bOk = false;
1451 if ( m_bOk )
1453 if (!m_xFonts)
1454 ReadFontCollection();
1456 // reading TxPF, TxSI
1457 PPTTextParagraphStyleAtomInterpreter aTxPFStyle;
1458 PPTTextSpecInfoAtomInterpreter aTxSIStyle; // styles (default language setting ... )
1460 DffRecordHeader* pEnvHd = aDocRecManager.GetRecordHeader( PPT_PST_Environment );
1461 if ( pEnvHd )
1463 pEnvHd->SeekToContent( rStCtrl );
1464 DffRecordHeader aTxPFStyleRecHd;
1465 if ( SeekToRec( rStCtrl, PPT_PST_TxPFStyleAtom, pEnvHd->GetRecEndFilePos(), &aTxPFStyleRecHd ) )
1466 aTxPFStyle.Read( rStCtrl, aTxPFStyleRecHd );
1468 pEnvHd->SeekToContent( rStCtrl );
1469 DffRecordHeader aTxSIStyleRecHd;
1470 if ( SeekToRec( rStCtrl, PPT_PST_TxSIStyleAtom, pEnvHd->GetRecEndFilePos(), &aTxSIStyleRecHd ) )
1472 aTxSIStyle.Read( rStCtrl, aTxSIStyleRecHd, PPT_PST_TxSIStyleAtom );
1473 #ifdef DBG_UTIL
1474 if ( !aTxSIStyle.bValid )
1476 if (!(rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT ))
1478 OSL_FAIL( "SdrTextSpecInfoAtomInterpreter::Ctor(): parsing error, this document needs to be analysed (SJ)" );
1481 #endif
1485 // TODO:: PPT_PST_TxPFStyleAtom
1487 // read SlidePersists
1488 m_pMasterPages.reset( new PptSlidePersistList );
1489 m_pSlidePages.reset( new PptSlidePersistList );
1490 m_pNotePages.reset( new PptSlidePersistList );
1492 // now always creating the handout page, it will be the first in our masterpage list
1493 std::unique_ptr<PptSlidePersistEntry> pE(new PptSlidePersistEntry);
1494 pE->aPersistAtom.nPsrReference = aDocAtom.nHandoutMasterPersist;
1495 pE->bHandoutMaster = true;
1496 if ( !aDocAtom.nHandoutMasterPersist )
1497 pE->bStarDrawFiller = true; // this is a dummy master page
1498 m_pMasterPages->insert(m_pMasterPages->begin(), std::move(pE));
1500 DffRecordHeader* pSlideListWithTextHd = aDocRecManager.GetRecordHeader( PPT_PST_SlideListWithText );
1501 PptSlidePersistEntry* pPreviousPersist = nullptr;
1502 DffRecordHeader* pSlideListHd = aDocRecManager.GetRecordHeader(PPT_PST_List);
1503 sal_uLong nPSTList = 0;
1504 if (pSlideListHd) nPSTList = pSlideListHd->GetRecBegFilePos();
1505 sal_uInt16 nRealPageNum = 0;
1506 // Normal PPT document has order of Master slides - Presentation slides - Note slides
1507 // for document with the order of Master slides - Note slides - Presentation slides
1508 // we need to swap the later two sections
1509 bool notePresentationSwap = false;
1510 for (sal_uInt16 nPageListNum = 0;
1511 pSlideListWithTextHd && nPageListNum < 3; ++nPageListNum)
1513 pSlideListWithTextHd->SeekToContent( rStCtrl );
1514 PptSlidePersistList* pPageList = nullptr;
1515 sal_uInt32 nSlideListWithTextHdEndOffset = pSlideListWithTextHd->GetRecEndFilePos();
1516 nRealPageNum = nPageListNum;
1517 while ( SeekToRec( rStCtrl, PPT_PST_SlidePersistAtom, nSlideListWithTextHdEndOffset ) )
1519 if ( pPreviousPersist )
1520 pPreviousPersist->nSlidePersistEndOffset = rStCtrl.Tell();
1521 std::unique_ptr<PptSlidePersistEntry> pE2(new PptSlidePersistEntry);
1522 ReadPptSlidePersistAtom( rStCtrl, pE2->aPersistAtom );
1523 pE2->nSlidePersistStartOffset = rStCtrl.Tell();
1524 // Note/Presentation section swap
1525 if (nPageListNum == 1 && pE2->nSlidePersistStartOffset < nPSTList)
1527 notePresentationSwap = true;
1529 if (notePresentationSwap)
1531 if (nPageListNum == 1) nRealPageNum = 2;
1532 else if (nPageListNum == 2) nRealPageNum = 1;
1535 pE2->ePageKind = PptPageKind(nRealPageNum);
1536 pPreviousPersist = pE2.get();
1537 if (!pPageList)
1539 pPageList = GetPageList(PptPageKind(nRealPageNum));
1541 pPageList->push_back(std::move(pE2));
1543 if ( pPreviousPersist )
1544 pPreviousPersist->nSlidePersistEndOffset = nSlideListWithTextHdEndOffset;
1545 pSlideListWithTextHd = aDocRecManager.GetRecordHeader( PPT_PST_SlideListWithText, SEEK_FROM_CURRENT );
1548 // we will ensure that there is at least one master page
1549 if (m_pMasterPages->size() == 1) // -> there is only a handout page available
1551 std::unique_ptr<PptSlidePersistEntry> pE2(new PptSlidePersistEntry);
1552 pE2->bStarDrawFiller = true; // this is a dummy master page
1553 m_pMasterPages->insert(m_pMasterPages->begin() + 1, std::move(pE2));
1556 // now we will insert at least one notes master for each master page
1557 sal_uInt16 nMasterPage;
1558 sal_uInt16 nMasterPages = m_pMasterPages->size() - 1;
1559 for ( nMasterPage = 0; nMasterPage < nMasterPages; nMasterPage++ )
1561 std::unique_ptr<PptSlidePersistEntry> pE2(new PptSlidePersistEntry);
1562 pE2->bNotesMaster = true;
1563 pE2->bStarDrawFiller = true; // this is a dummy master page
1564 if ( !nMasterPage && aDocAtom.nNotesMasterPersist )
1565 { // special treatment for the first notes master
1566 pE2->aPersistAtom.nPsrReference = aDocAtom.nNotesMasterPersist;
1567 pE2->bStarDrawFiller = false; // this is a dummy master page
1569 m_pMasterPages->insert(m_pMasterPages->begin() + ((nMasterPage + 1) << 1), std::move(pE2));
1572 // read for each page the SlideAtom respectively the NotesAtom if it exists
1573 for (sal_uInt16 nPageListNum = 0; nPageListNum < 3; ++nPageListNum)
1575 PptSlidePersistList* pPageList = GetPageList( PptPageKind( nPageListNum ) );
1576 for ( size_t nPageNum = 0; nPageNum < pPageList->size(); nPageNum++ )
1578 PptSlidePersistEntry& rE2 = (*pPageList)[ nPageNum ];
1579 sal_uLong nPersist = rE2.aPersistAtom.nPsrReference;
1580 if ( ( nPersist > 0 ) && ( nPersist < m_nPersistPtrCnt ) )
1582 sal_uLong nFPos = m_pPersistPtr[ nPersist ];
1583 if ( nFPos < nStreamLen )
1585 rStCtrl.Seek( nFPos );
1586 DffRecordHeader aSlideHd;
1587 ReadDffRecordHeader( rStCtrl, aSlideHd );
1588 if ( SeekToRec( rStCtrl, PPT_PST_SlideAtom, aSlideHd.GetRecEndFilePos() ) )
1589 ReadPptSlideAtom( rStCtrl, rE2.aSlideAtom );
1590 else if ( SeekToRec( rStCtrl, PPT_PST_NotesAtom, aSlideHd.GetRecEndFilePos() ) )
1591 ReadPptNotesAtom( rStCtrl, rE2.aNotesAtom );
1592 aSlideHd.SeekToContent( rStCtrl );
1594 DffRecordHeader aPPTDrawingHd;
1595 if ( SeekToRec( rStCtrl, PPT_PST_PPDrawing, aSlideHd.GetRecEndFilePos(), &aPPTDrawingHd ) )
1597 DffRecordHeader aPPTDgContainer;
1598 if ( SeekToRec( rStCtrl, DFF_msofbtDgContainer, aPPTDrawingHd.GetRecEndFilePos(), &aPPTDgContainer ) )
1600 if ( SeekToRec( rStCtrl, DFF_msofbtDg, aPPTDrawingHd.GetRecEndFilePos() ) )
1602 DffRecordHeader aDgRecordHeader;
1603 ReadDffRecordHeader( rStCtrl, aDgRecordHeader );
1604 rE2.nDrawingDgId = aDgRecordHeader.nRecInstance;
1605 aDgRecordHeader.SeekToEndOfRecord( rStCtrl );
1607 if ( SeekToRec( rStCtrl, DFF_msofbtSolverContainer, aPPTDgContainer.GetRecEndFilePos() ) )
1609 rE2.xSolverContainer.reset(new SvxMSDffSolverContainer);
1610 ReadSvxMSDffSolverContainer(rStCtrl, *rE2.xSolverContainer);
1612 aPPTDgContainer.SeekToBegOfRecord( rStCtrl );
1613 SetDgContainer( rStCtrl ); // set this, so that the escherimport is knowing of our drawings
1616 // office xp is supporting more than one stylesheet
1617 if ( ( rE2.ePageKind == PPT_MASTERPAGE ) && ( rE2.aSlideAtom.nMasterId == 0 ) && !rE2.bNotesMaster )
1619 PPTTextSpecInfo aTxSI( 0 );
1620 if ( aTxSIStyle.bValid && !aTxSIStyle.aList.empty() )
1621 aTxSI = aTxSIStyle.aList[ 0 ];
1623 rE2.xStyleSheet = std::make_unique<PPTStyleSheet>(aSlideHd, rStCtrl, *this, aTxPFStyle, aTxSI);
1624 m_pDefaultSheet = rE2.xStyleSheet.get();
1626 if ( SeekToRec( rStCtrl, PPT_PST_ColorSchemeAtom, aSlideHd.GetRecEndFilePos() ) )
1627 ReadPptColorSchemeAtom( rStCtrl, rE2.aColorScheme );
1628 else
1630 OSL_FAIL( "SdrPowerPointImport::Ctor(): could not get SlideColorScheme! (SJ)" );
1633 else
1635 OSL_FAIL("SdrPowerPointImport::Ctor(): Persist entry is flawed! (SJ)");
1640 DffRecordHeader* pHeadersFootersHd = aDocRecManager.GetRecordHeader( PPT_PST_HeadersFooters );
1641 if ( pHeadersFootersHd )
1643 HeaderFooterEntry aNormalMaster, aNotesMaster;
1644 for ( ; pHeadersFootersHd; pHeadersFootersHd = aDocRecManager.GetRecordHeader( PPT_PST_HeadersFooters, SEEK_FROM_CURRENT ) )
1646 if ( pHeadersFootersHd->nRecInstance == 3 ) // normal master
1647 ImportHeaderFooterContainer( *pHeadersFootersHd, aNormalMaster );
1648 else if ( pHeadersFootersHd->nRecInstance == 4 ) // notes master
1649 ImportHeaderFooterContainer( *pHeadersFootersHd, aNotesMaster );
1651 for (size_t i = 0; i < m_pMasterPages->size(); i++)
1653 if ((*m_pMasterPages)[ i ].bNotesMaster)
1654 (*m_pMasterPages)[ i ].xHeaderFooterEntry.reset(new HeaderFooterEntry(aNotesMaster));
1655 else
1656 (*m_pMasterPages)[ i ].xHeaderFooterEntry.reset(new HeaderFooterEntry(aNormalMaster));
1661 if ( ( rStCtrl.GetError() != ERRCODE_NONE ) || ( m_pDefaultSheet == nullptr ) )
1662 m_bOk = false;
1663 m_pPPTStyleSheet = m_pDefaultSheet;
1664 rStCtrl.Seek( 0 );
1667 SdrPowerPointImport::~SdrPowerPointImport()
1669 m_pMasterPages.reset();
1670 m_pSlidePages.reset();
1671 m_pNotePages.reset();
1674 bool PPTConvertOCXControls::ReadOCXStream( tools::SvRef<SotStorage>& rSrc,
1675 css::uno::Reference< css::drawing::XShape > *pShapeRef )
1677 bool bRes = false;
1678 uno::Reference< form::XFormComponent > xFComp;
1679 if ( mpPPTImporter && mpPPTImporter->ReadFormControl( rSrc, xFComp ) )
1681 if ( xFComp.is() )
1683 css::awt::Size aSz; // not used in import
1684 bRes = InsertControl( xFComp, aSz,pShapeRef, false/*bFloatingCtrl*/);
1687 return bRes;
1690 bool PPTConvertOCXControls::InsertControl(
1691 const css::uno::Reference< css::form::XFormComponent > &rFComp,
1692 const css::awt::Size& rSize,
1693 css::uno::Reference< css::drawing::XShape > *pShape,
1694 bool /*bFloatingCtrl*/)
1696 bool bRetValue = false;
1699 css::uno::Reference< css::drawing::XShape > xShape;
1701 const css::uno::Reference< css::container::XIndexContainer > & rFormComps =
1702 GetFormComps();
1704 css::uno::Any aTmp( &rFComp, cppu::UnoType<css::form::XFormComponent>::get() );
1706 rFormComps->insertByIndex( rFormComps->getCount(), aTmp );
1708 const css::uno::Reference< css::lang::XMultiServiceFactory > & rServiceFactory =
1709 GetServiceFactory();
1710 if( rServiceFactory.is() )
1712 css::uno::Reference< css::uno::XInterface > xCreate = rServiceFactory
1713 ->createInstance( "com.sun.star.drawing.ControlShape" );
1714 if( xCreate.is() )
1716 xShape.set(xCreate, css::uno::UNO_QUERY);
1717 if ( xShape.is() )
1719 xShape->setSize(rSize);
1720 // set the Control-Model at the Control-Shape
1721 css::uno::Reference< css::drawing::XControlShape > xControlShape( xShape,
1722 css::uno::UNO_QUERY );
1723 css::uno::Reference< css::awt::XControlModel > xControlModel( rFComp,
1724 css::uno::UNO_QUERY );
1725 if ( xControlShape.is() && xControlModel.is() )
1727 xControlShape->setControl( xControlModel );
1728 if (pShape)
1729 *pShape = xShape;
1730 bRetValue = true;
1736 catch( ... )
1738 bRetValue = false;
1740 return bRetValue;
1742 void PPTConvertOCXControls::GetDrawPage()
1744 if( xDrawPage.is() || !mxModel.is() )
1745 return;
1747 css::uno::Reference< css::drawing::XDrawPages > xDrawPages;
1748 switch( ePageKind )
1750 case PPT_SLIDEPAGE :
1751 case PPT_NOTEPAGE :
1753 css::uno::Reference< css::drawing::XDrawPagesSupplier >
1754 xDrawPagesSupplier( mxModel, css::uno::UNO_QUERY);
1755 if ( xDrawPagesSupplier.is() )
1756 xDrawPages = xDrawPagesSupplier->getDrawPages();
1758 break;
1760 case PPT_MASTERPAGE :
1762 css::uno::Reference< css::drawing::XMasterPagesSupplier >
1763 xMasterPagesSupplier( mxModel, css::uno::UNO_QUERY);
1764 if ( xMasterPagesSupplier.is() )
1765 xDrawPages = xMasterPagesSupplier->getMasterPages();
1767 break;
1769 if ( xDrawPages.is() && xDrawPages->getCount() )
1771 xDrawPages->getCount();
1772 css::uno::Any aAny( xDrawPages->getByIndex( xDrawPages->getCount() - 1 ) );
1773 aAny >>= xDrawPage;
1777 static bool SdrPowerPointOLEDecompress( SvStream& rOutput, SvStream& rInput, sal_uInt32 nInputSize )
1779 sal_uInt32 nOldPos = rInput.Tell();
1780 std::unique_ptr<char[]> pBuf(new char[ nInputSize ]);
1781 rInput.ReadBytes(pBuf.get(), nInputSize);
1782 ZCodec aZCodec( 0x8000, 0x8000 );
1783 aZCodec.BeginCompression();
1784 SvMemoryStream aSource( pBuf.get(), nInputSize, StreamMode::READ );
1785 aZCodec.Decompress( aSource, rOutput );
1786 const bool bSuccess(0 != aZCodec.EndCompression());
1787 rInput.Seek( nOldPos );
1788 return bSuccess;
1791 // #i32596# - add new parameter <_nCalledByGroup>
1792 rtl::Reference<SdrObject> SdrPowerPointImport::ImportOLE( sal_uInt32 nOLEId,
1793 const Graphic& rGraf,
1794 const tools::Rectangle& rBoundRect,
1795 const tools::Rectangle& rVisArea,
1796 const int /*_nCalledByGroup*/ ) const
1798 rtl::Reference<SdrObject> pRet;
1800 sal_uInt32 nOldPos = rStCtrl.Tell();
1802 Graphic aGraphic( rGraf );
1804 if ( const_cast<SdrPowerPointImport*>(this)->maShapeRecords.SeekToContent( rStCtrl, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) )
1806 DffRecordHeader aPlaceHd;
1808 auto nEndRecPos = SanitizeEndPos(rStCtrl, const_cast<SdrPowerPointImport*>(this)->maShapeRecords.Current()->GetRecEndFilePos());
1809 while ( ( rStCtrl.GetError() == ERRCODE_NONE )
1810 && ( rStCtrl.Tell() < nEndRecPos ) )
1812 ReadDffRecordHeader( rStCtrl, aPlaceHd );
1813 if ( aPlaceHd.nRecType == PPT_PST_RecolorInfoAtom )
1815 const_cast<SdrPowerPointImport*>(this)->RecolorGraphic( rStCtrl, aPlaceHd.nRecLen, aGraphic );
1816 break;
1818 else
1820 if (!aPlaceHd.SeekToEndOfRecord(rStCtrl))
1821 break;
1826 for (PPTOleEntry& rOe : const_cast<SdrPowerPointImport*>(this)->aOleObjectList)
1828 if ( rOe.nId != nOLEId )
1829 continue;
1831 rStCtrl.Seek( rOe.nRecHdOfs );
1833 DffRecordHeader aHd;
1834 ReadDffRecordHeader( rStCtrl, aHd );
1836 sal_uInt32 nLen = aHd.nRecLen - 4;
1837 if ( static_cast<sal_Int32>(nLen) > 0 )
1839 bool bSuccess = false;
1841 rStCtrl.SeekRel( 4 );
1843 ::utl::TempFileFast aTmpFile;
1844 SvStream* pDest = aTmpFile.GetStream(StreamMode::READWRITE);
1845 if (pDest)
1847 bSuccess = SdrPowerPointOLEDecompress( *pDest, rStCtrl, nLen );
1849 if ( bSuccess )
1851 pDest->Seek(0);
1852 Storage* pObjStor = new Storage(*pDest, false);
1853 tools::SvRef<SotStorage> xObjStor( new SotStorage( pObjStor ) );
1854 if ( xObjStor.is() && !xObjStor->GetError() )
1856 if ( xObjStor->GetClassName() == SvGlobalName() )
1858 xObjStor->SetClass( SvGlobalName( pObjStor->GetClassId() ), pObjStor->GetFormat(), pObjStor->GetUserName() );
1860 tools::SvRef<SotStorageStream> xSrcTst = xObjStor->OpenSotStream( "\1Ole" );
1861 if ( xSrcTst.is() )
1863 sal_uInt8 aTestA[ 10 ];
1864 bool bGetItAsOle = (sizeof(aTestA) == xSrcTst->ReadBytes(aTestA, sizeof(aTestA)));
1865 if ( !bGetItAsOle )
1866 { // maybe there is a contents stream in here
1867 xSrcTst = xObjStor->OpenSotStream( "Contents", StreamMode::READWRITE | StreamMode::NOCREATE );
1868 bGetItAsOle = (xSrcTst.is() &&
1869 sizeof(aTestA) == xSrcTst->ReadBytes(aTestA, sizeof(aTestA)));
1871 if ( bGetItAsOle )
1873 OUString aNm;
1874 // if ( nSvxMSDffOLEConvFlags )
1876 uno::Reference < embed::XStorage > xDestStorage( rOe.pShell->GetStorage() );
1877 uno::Reference < embed::XEmbeddedObject > xObj =
1878 CheckForConvertToSOObj(nSvxMSDffOLEConvFlags, *xObjStor, xDestStorage, rGraf, rVisArea, maBaseURL);
1879 if( xObj.is() )
1881 rOe.pShell->getEmbeddedObjectContainer().InsertEmbeddedObject( xObj, aNm );
1883 svt::EmbeddedObjectRef aObj( xObj, rOe.nAspect );
1885 // TODO/LATER: need MediaType for Graphic
1886 aObj.SetGraphic( rGraf, OUString() );
1887 pRet = new SdrOle2Obj(
1888 *pSdrModel,
1889 aObj,
1890 aNm,
1891 rBoundRect);
1894 if ( !pRet && ( rOe.nType == PPT_PST_ExControl ) )
1896 uno::Reference< frame::XModel > xModel( rOe.pShell->GetModel() );
1897 PPTConvertOCXControls aPPTConvertOCXControls( this, xModel, m_eCurrentPageKind );
1898 css::uno::Reference< css::drawing::XShape > xShape;
1899 if ( aPPTConvertOCXControls.ReadOCXStream( xObjStor, &xShape ) )
1900 pRet = SdrObject::getSdrObjectFromXShape(xShape);
1903 if ( !pRet )
1905 aNm = rOe.pShell->getEmbeddedObjectContainer().CreateUniqueObjectName();
1907 // object is not an own object
1908 const css::uno::Reference < css::embed::XStorage >& rStorage = rOe.pShell->GetStorage();
1909 if (rStorage.is())
1911 tools::SvRef<SotStorage> xTarget = SotStorage::OpenOLEStorage(rStorage, aNm, StreamMode::READWRITE);
1912 if (xObjStor.is() && xTarget.is())
1914 xObjStor->CopyTo(xTarget.get());
1915 if (!xTarget->GetError())
1916 xTarget->Commit();
1918 xTarget.clear();
1921 uno::Reference < embed::XEmbeddedObject > xObj =
1922 rOe.pShell->getEmbeddedObjectContainer().GetEmbeddedObject( aNm );
1923 if ( xObj.is() )
1925 if ( rOe.nAspect != embed::Aspects::MSOLE_ICON )
1927 //TODO/LATER: keep on hacking?!
1928 // we don't want to be modified
1929 //xInplaceObj->EnableSetModified( sal_False );
1930 if ( rVisArea.IsEmpty() )
1932 MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( rOe.nAspect ) );
1933 Size aSize( OutputDevice::LogicToLogic( aGraphic.GetPrefSize(),
1934 aGraphic.GetPrefMapMode(), MapMode( aMapUnit ) ) );
1936 awt::Size aSz;
1937 aSz.Width = aSize.Width();
1938 aSz.Height = aSize.Height();
1939 xObj->setVisualAreaSize( rOe.nAspect, aSz );
1941 else
1943 awt::Size aSize( rVisArea.GetSize().Width(), rVisArea.GetSize().Height() );
1944 xObj->setVisualAreaSize( rOe.nAspect, aSize );
1946 //xInplaceObj->EnableSetModified( sal_True );
1949 svt::EmbeddedObjectRef aObj( xObj, rOe.nAspect );
1951 // TODO/LATER: need MediaType for Graphic
1952 aObj.SetGraphic( aGraphic, OUString() );
1954 pRet = new SdrOle2Obj(
1955 *pSdrModel,
1956 aObj,
1957 aNm,
1958 rBoundRect);
1965 aTmpFile.CloseStream();
1968 rStCtrl.Seek( nOldPos );
1970 return pRet;
1973 std::unique_ptr<SvMemoryStream> SdrPowerPointImport::ImportExOleObjStg( sal_uInt32 nPersistPtr, sal_uInt32& nOleId ) const
1975 std::unique_ptr<SvMemoryStream> pRet;
1976 if ( nPersistPtr && ( nPersistPtr < m_nPersistPtrCnt ) )
1978 sal_uInt32 nOldPos, nOfs = m_pPersistPtr[ nPersistPtr ];
1979 nOldPos = rStCtrl.Tell();
1980 rStCtrl.Seek( nOfs );
1981 DffRecordHeader aHd;
1982 ReadDffRecordHeader( rStCtrl, aHd );
1983 if ( aHd.nRecType == DFF_PST_ExOleObjStg )
1985 sal_uInt32 nLen = aHd.nRecLen - 4;
1986 if ( static_cast<sal_Int32>(nLen) > 0 )
1988 rStCtrl.ReadUInt32( nOleId );
1989 pRet.reset(new SvMemoryStream);
1990 ZCodec aZCodec( 0x8000, 0x8000 );
1991 aZCodec.BeginCompression();
1992 aZCodec.Decompress( rStCtrl, *pRet );
1993 if ( !aZCodec.EndCompression() )
1995 pRet.reset();
1999 rStCtrl.Seek( nOldPos );
2001 return pRet;
2004 void SdrPowerPointImport::SeekOle( SfxObjectShell* pShell, sal_uInt32 nFilterOptions )
2006 if ( !pShell )
2007 return;
2009 DffRecordHeader* pHd;
2011 sal_uInt32 nOldPos = rStCtrl.Tell();
2012 if ( nFilterOptions & 1 )
2014 pHd = aDocRecManager.GetRecordHeader( PPT_PST_List );
2015 if ( pHd )
2017 // we try to locate the basic atom
2018 pHd->SeekToContent( rStCtrl );
2019 if ( SeekToRec( rStCtrl, PPT_PST_VBAInfo, pHd->GetRecEndFilePos(), pHd ) )
2021 if ( SeekToRec( rStCtrl, PPT_PST_VBAInfoAtom, pHd->GetRecEndFilePos(), pHd ) )
2023 sal_uInt32 nPersistPtr, nIDoNotKnow1, nIDoNotKnow2;
2024 rStCtrl.ReadUInt32( nPersistPtr )
2025 .ReadUInt32( nIDoNotKnow1 )
2026 .ReadUInt32( nIDoNotKnow2 );
2028 sal_uInt32 nOleId;
2029 std::unique_ptr<SvMemoryStream> pBas = ImportExOleObjStg( nPersistPtr, nOleId );
2030 if ( pBas )
2032 tools::SvRef<SotStorage> xSource( new SotStorage( pBas.release(), true ) );
2033 tools::SvRef<SotStorage> xDest( new SotStorage( new SvMemoryStream(), true ) );
2034 if ( xSource.is() && xDest.is() )
2036 // is this a visual basic storage ?
2037 tools::SvRef<SotStorage> xSubStorage = xSource->OpenSotStorage( "VBA",
2038 StreamMode::READWRITE | StreamMode::NOCREATE | StreamMode::SHARE_DENYALL );
2039 if( xSubStorage.is() && ( ERRCODE_NONE == xSubStorage->GetError() ) )
2041 tools::SvRef<SotStorage> xMacros = xDest->OpenSotStorage( "MACROS" );
2042 if ( xMacros.is() )
2044 SvStorageInfoList aList;
2045 xSource->FillInfoList( &aList );
2046 SvStorageInfoList::size_type i;
2048 bool bCopied = true;
2049 for ( i = 0; i < aList.size(); i++ ) // copy all entries
2051 const SvStorageInfo& rInfo = aList[ i ];
2052 if ( !xSource->CopyTo( rInfo.GetName(), xMacros.get(), rInfo.GetName() ) )
2053 bCopied = false;
2055 if ( i && bCopied )
2057 uno::Reference < embed::XStorage > xDoc( pShell->GetStorage() );
2058 if ( xDoc.is() )
2060 tools::SvRef<SotStorage> xVBA = SotStorage::OpenOLEStorage( xDoc, SvxImportMSVBasic::GetMSBasicStorageName() );
2061 if ( xVBA.is() && ( xVBA->GetError() == ERRCODE_NONE ) )
2063 tools::SvRef<SotStorage> xSubVBA = xVBA->OpenSotStorage( "_MS_VBA_Overhead" );
2064 if ( xSubVBA.is() && ( xSubVBA->GetError() == ERRCODE_NONE ) )
2066 tools::SvRef<SotStorageStream> xOriginal = xSubVBA->OpenSotStream( "_MS_VBA_Overhead2" );
2067 if ( xOriginal.is() && ( xOriginal->GetError() == ERRCODE_NONE ) )
2069 if ( nPersistPtr && ( nPersistPtr < m_nPersistPtrCnt ) )
2071 rStCtrl.Seek( m_pPersistPtr[ nPersistPtr ] );
2072 ReadDffRecordHeader( rStCtrl, *pHd );
2074 xOriginal->WriteUInt32( nIDoNotKnow1 )
2075 .WriteUInt32( nIDoNotKnow2 );
2077 sal_uInt32 nToCopy, nBufSize;
2078 nToCopy = pHd->nRecLen;
2079 std::unique_ptr<sal_uInt8[]> pBuf(new sal_uInt8[ 0x40000 ]); // 256KB Buffer
2080 while ( nToCopy )
2082 nBufSize = ( nToCopy >= 0x40000 ) ? 0x40000 : nToCopy;
2083 rStCtrl.ReadBytes(pBuf.get(), nBufSize);
2084 xOriginal->WriteBytes(pBuf.get(), nBufSize);
2085 nToCopy -= nBufSize;
2091 xVBA->Commit();
2102 pHd = aDocRecManager.GetRecordHeader( PPT_PST_ExObjList );
2103 if ( pHd )
2105 DffRecordHeader* pExEmbed = nullptr;
2107 pHd->SeekToBegOfRecord( rStCtrl );
2108 DffRecordManager aExObjListManager( rStCtrl );
2109 sal_uInt16 i, nRecType(PPT_PST_ExEmbed);
2111 for ( i = 0; i < 2; i++ )
2113 switch ( i )
2115 case 0 : nRecType = PPT_PST_ExEmbed; break;
2116 case 1 : nRecType = PPT_PST_ExControl; break;
2118 for ( pExEmbed = aExObjListManager.GetRecordHeader( nRecType );
2119 pExEmbed; pExEmbed = aExObjListManager.GetRecordHeader( nRecType, SEEK_FROM_CURRENT ) )
2121 pExEmbed->SeekToContent( rStCtrl );
2123 DffRecordHeader aExOleAtHd;
2124 if ( SeekToRec( rStCtrl, PPT_PST_ExOleObjAtom, pExEmbed->GetRecEndFilePos(), &aExOleAtHd ) )
2126 PptExOleObjAtom aAt;
2127 ReadPptExOleObjAtom( rStCtrl, aAt );
2129 if ( aAt.nPersistPtr && ( aAt.nPersistPtr < m_nPersistPtrCnt ) )
2131 rStCtrl.Seek( m_pPersistPtr[ aAt.nPersistPtr ] );
2132 DffRecordHeader aHd;
2133 ReadDffRecordHeader( rStCtrl, aHd );
2134 if ( aHd.nRecType == DFF_PST_ExOleObjStg )
2136 sal_uInt32 nId;
2137 rStCtrl.ReadUInt32( nId );
2138 aOleObjectList.emplace_back(
2139 aAt.nId, aHd.nFilePos, pShell, nRecType, aAt.nAspect );
2146 rStCtrl.Seek( nOldPos );
2149 bool SdrPowerPointImport::ReadFontCollection()
2151 bool bRet = false;
2152 DffRecordHeader* pEnvHd = aDocRecManager.GetRecordHeader( PPT_PST_Environment );
2153 if ( pEnvHd )
2155 sal_uInt64 nOldFPos = rStCtrl.Tell(); // remember FilePos for restoring it later
2156 pEnvHd->SeekToContent( rStCtrl );
2157 DffRecordHeader aListHd;
2158 if ( SeekToRec( rStCtrl, PPT_PST_FontCollection, pEnvHd->GetRecEndFilePos(), &aListHd ) )
2160 sal_uInt16 nCount2 = 0;
2161 while ( SeekToRec( rStCtrl, PPT_PST_FontEntityAtom, aListHd.GetRecEndFilePos() ) )
2163 bRet = true;
2164 if (!m_xFonts)
2165 m_xFonts.emplace();
2166 PptFontEntityAtom aFontAtom;
2167 ReadPptFontEntityAtom( rStCtrl, aFontAtom );
2169 vcl::Font aFont;
2170 aFont.SetCharSet( aFontAtom.eCharSet );
2171 aFont.SetFamilyName( aFontAtom.aName );
2172 aFont.SetFamily( aFontAtom.eFamily );
2173 aFont.SetPitch( aFontAtom.ePitch );
2174 aFont.SetFontHeight( 100 );
2176 // following block is necessary, because our old PowerPoint export did not set the
2177 // correct charset
2178 if ( aFontAtom.aName.equalsIgnoreAsciiCase( "Wingdings" ) ||
2179 aFontAtom.aName.equalsIgnoreAsciiCase( "Wingdings 2" ) ||
2180 aFontAtom.aName.equalsIgnoreAsciiCase( "Wingdings 3" ) ||
2181 aFontAtom.aName.equalsIgnoreAsciiCase( "Monotype Sorts" ) ||
2182 aFontAtom.aName.equalsIgnoreAsciiCase( "Monotype Sorts 2" ) ||
2183 aFontAtom.aName.equalsIgnoreAsciiCase( "Webdings" ) ||
2184 aFontAtom.aName.equalsIgnoreAsciiCase( "StarBats" ) ||
2185 aFontAtom.aName.equalsIgnoreAsciiCase( "StarMath" ) ||
2186 aFontAtom.aName.equalsIgnoreAsciiCase( "ZapfDingbats" ) )
2188 aFontAtom.eCharSet = RTL_TEXTENCODING_SYMBOL;
2190 m_xFonts->insert(m_xFonts->begin() + nCount2++, std::move(aFontAtom));
2193 rStCtrl.Seek( nOldFPos ); // restore FilePos
2195 return bRet;
2198 PptSlidePersistList* SdrPowerPointImport::GetPageList(PptPageKind ePageKind) const
2200 switch (ePageKind)
2202 case PPT_MASTERPAGE:
2203 return m_pMasterPages.get();
2204 case PPT_SLIDEPAGE:
2205 return m_pSlidePages.get();
2206 case PPT_NOTEPAGE:
2207 return m_pNotePages.get();
2209 return nullptr;
2212 SdrOutliner* SdrPowerPointImport::GetDrawOutliner( SdrTextObj const * pSdrText )
2214 if ( !pSdrText )
2215 return nullptr;
2216 else
2217 return &pSdrText->ImpGetDrawOutliner();
2221 SdrObject* SdrPowerPointImport::ReadObjText( PPTTextObj* pTextObj, SdrObject* pSdrObj, SdPageCapsule pPage ) const
2223 SdrTextObj* pText = DynCastSdrTextObj( pSdrObj );
2224 if ( pText )
2226 if ( !ApplyTextObj( pTextObj, pText, pPage, nullptr, nullptr ) )
2227 pSdrObj = nullptr;
2229 return pSdrObj;
2232 SdrObject* SdrPowerPointImport::ApplyTextObj( PPTTextObj* pTextObj, SdrTextObj* pSdrText, SdPageCapsule /*pPage*/,
2233 SfxStyleSheet* pSheet, SfxStyleSheet** ppStyleSheetAry ) const
2235 SdrTextObj* pText = pSdrText;
2236 if ( pTextObj->Count() )
2238 TSS_Type nDestinationInstance = pTextObj->GetDestinationInstance() ;
2239 SdrOutliner& rOutliner = pText->ImpGetDrawOutliner();
2240 bool bUndoEnabled = rOutliner.IsUndoEnabled();
2241 rOutliner.EnableUndo(false);
2243 if ( ( pText->GetObjInventor() == SdrInventor::Default ) && ( pText->GetObjIdentifier() == SdrObjKind::TitleText ) ) // Outliner-Style for Title-Text object?!? (->of DL)
2244 rOutliner.Init( OutlinerMode::TitleObject ); // Outliner reset
2246 bool bOldUpdateMode = rOutliner.SetUpdateLayout( false );
2247 if ( pSheet )
2249 if ( rOutliner.GetStyleSheet( 0 ) != pSheet )
2250 rOutliner.SetStyleSheet( 0, pSheet );
2252 rOutliner.SetVertical( pTextObj->GetVertical() );
2253 for ( PPTParagraphObj* pPara = pTextObj->First(); pPara; pPara = pTextObj->Next() )
2255 sal_uInt32 nTextSize = pPara->GetTextSize();
2256 if ( ! ( nTextSize & 0xffff0000 ) )
2258 PPTPortionObj* pPortion;
2259 std::unique_ptr<sal_Unicode[]> pParaText(new sal_Unicode[ nTextSize ]);
2260 sal_Int32 nCurrentIndex = 0;
2261 for ( pPortion = pPara->First(); pPortion; pPortion = pPara->Next() )
2263 if ( pPortion->mpFieldItem )
2264 pParaText[ nCurrentIndex++ ] = ' ';
2265 else
2267 sal_Int32 nCharacters = pPortion->Count();
2268 const sal_Unicode* pSource = pPortion->maString.getStr();
2269 sal_Unicode* pDest = pParaText.get() + nCurrentIndex;
2271 sal_uInt32 nFont;
2272 pPortion->GetAttrib( PPT_CharAttr_Font, nFont, pTextObj->GetInstance() );
2273 const PptFontEntityAtom* pFontEnityAtom = GetFontEnityAtom( nFont );
2274 if ( pFontEnityAtom && ( pFontEnityAtom->eCharSet == RTL_TEXTENCODING_SYMBOL ) )
2276 sal_Unicode nUnicode;
2277 for (sal_Int32 i = 0; i < nCharacters; i++ )
2279 nUnicode = pSource[ i ];
2280 if ( ! ( nUnicode & 0xff00 ) )
2281 nUnicode |= 0xf000;
2282 pDest[ i ] = nUnicode;
2285 else
2286 memcpy( pDest, pSource, nCharacters << 1 );
2287 nCurrentIndex += nCharacters;
2290 sal_Int32 nParaIndex = pTextObj->GetCurrentIndex();
2291 SfxStyleSheet* pS = ppStyleSheetAry ? ppStyleSheetAry[ pPara->mxParaSet->mnDepth ] : pSheet;
2293 ESelection aSelection( nParaIndex, 0, nParaIndex, 0 );
2294 rOutliner.Insert( OUString(), nParaIndex, pPara->mxParaSet->mnDepth );
2295 rOutliner.QuickInsertText( OUString(pParaText.get(), nCurrentIndex), aSelection );
2296 rOutliner.SetParaAttribs( nParaIndex, rOutliner.GetEmptyItemSet() );
2297 if ( pS )
2298 rOutliner.SetStyleSheet( nParaIndex, pS );
2300 for ( pPortion = pPara->First(); pPortion; pPortion = pPara->Next() )
2302 SfxItemSet aPortionAttribs( rOutliner.GetEmptyItemSet() );
2303 std::unique_ptr<SvxFieldItem> pFieldItem(pPortion->GetTextField());
2304 if ( pFieldItem )
2306 rOutliner.QuickInsertField( *pFieldItem, ESelection( nParaIndex, aSelection.nEndPos, nParaIndex, aSelection.nEndPos + 1 ) );
2307 aSelection.nEndPos++;
2309 else
2311 const sal_Unicode *pF, *pPtr = pPortion->maString.getStr();
2312 const sal_Unicode *pMax = pPtr + pPortion->maString.getLength();
2313 sal_Int32 nLen;
2314 for ( pF = pPtr; pPtr < pMax; pPtr++ )
2316 if ( *pPtr == 0xb )
2318 nLen = pPtr - pF;
2319 if ( nLen )
2320 aSelection.nEndPos =
2321 sal::static_int_cast< sal_uInt16 >(
2322 aSelection.nEndPos + nLen );
2323 pF = pPtr + 1;
2324 rOutliner.QuickInsertLineBreak( ESelection( nParaIndex, aSelection.nEndPos, nParaIndex, aSelection.nEndPos + 1 ) );
2325 aSelection.nEndPos++;
2328 nLen = pPtr - pF;
2329 if ( nLen )
2330 aSelection.nEndPos = sal::static_int_cast< sal_uInt16 >(
2331 aSelection.nEndPos + nLen );
2333 pPortion->ApplyTo( aPortionAttribs, const_cast<SdrPowerPointImport&>(*this), nDestinationInstance, pTextObj );
2334 rOutliner.QuickSetAttribs( aPortionAttribs, aSelection );
2335 aSelection.nStartPos = aSelection.nEndPos;
2337 std::optional< sal_Int16 > oStartNumbering;
2338 SfxItemSet aParagraphAttribs( rOutliner.GetEmptyItemSet() );
2339 pPara->ApplyTo( aParagraphAttribs, oStartNumbering, *this, nDestinationInstance );
2341 sal_uInt32 nIsBullet2 = 0; //, nInstance = nDestinationInstance != 0xffffffff ? nDestinationInstance : pTextObj->GetInstance();
2342 pPara->GetAttrib( PPT_ParaAttr_BulletOn, nIsBullet2, nDestinationInstance );
2343 if ( !nIsBullet2 )
2344 aParagraphAttribs.Put( SfxBoolItem( EE_PARA_BULLETSTATE, false ) );
2345 else
2346 aParagraphAttribs.Put( SfxInt16Item(EE_PARA_OUTLLEVEL, pPara->mxParaSet->mnDepth));
2348 if ( !aSelection.nStartPos ) // in PPT empty paragraphs never gets a bullet
2350 aParagraphAttribs.Put( SfxBoolItem( EE_PARA_BULLETSTATE, false ) );
2352 aSelection.nStartPos = 0;
2353 rOutliner.QuickSetAttribs( aParagraphAttribs, aSelection );
2356 std::optional<OutlinerParaObject> pNewText = rOutliner.CreateParaObject();
2357 rOutliner.Clear();
2358 rOutliner.SetUpdateLayout( bOldUpdateMode );
2359 rOutliner.EnableUndo(bUndoEnabled);
2360 pText->SetOutlinerParaObject( std::move(pNewText) );
2362 return pText;
2365 bool SdrPowerPointImport::SeekToDocument( DffRecordHeader* pRecHd ) const
2367 bool bRet;
2368 sal_uInt64 nOldFPos = rStCtrl.Tell(); // remember FilePos for restoring it, if the situation should happen
2369 rStCtrl.Seek( m_nDocStreamPos );
2370 DffRecordHeader aDocHd;
2371 ReadDffRecordHeader( rStCtrl, aDocHd );
2372 bRet = aDocHd.nRecType == PPT_PST_Document;
2373 if ( bRet )
2375 if ( pRecHd )
2376 *pRecHd = aDocHd;
2377 else
2378 aDocHd.SeekToBegOfRecord( rStCtrl );
2380 if ( !bRet )
2381 rStCtrl.Seek( nOldFPos ); // restore FilePos
2382 return bRet;
2385 bool SdrPowerPointImport::SeekToContentOfProgTag( sal_Int32 nVersion, SvStream& rSt,
2386 const DffRecordHeader& rSourceHd, DffRecordHeader& rContentHd )
2388 bool bRetValue = false;
2389 sal_uInt32 nOldPos = rSt.Tell();
2391 DffRecordHeader aProgTagsHd, aProgTagBinaryDataHd;
2392 rSourceHd.SeekToContent( rSt );
2393 bool bFound = rSourceHd.nRecType == PPT_PST_ProgTags;
2394 if ( !bFound )
2395 bFound = SeekToRec( rSt, PPT_PST_ProgTags, rSourceHd.GetRecEndFilePos(), &aProgTagsHd );
2396 if ( bFound )
2398 while( SeekToRec( rSt, PPT_PST_ProgBinaryTag, aProgTagsHd.GetRecEndFilePos(), &aProgTagBinaryDataHd ) )
2400 ReadDffRecordHeader( rSt, rContentHd );
2401 if ( rContentHd.nRecType == PPT_PST_CString )
2403 sal_uInt16 n = 6;
2404 sal_uInt32 i = rContentHd.nRecLen >> 1;
2405 if ( i > n )
2407 OUString aPre = read_uInt16s_ToOUString(rSt, n);
2408 n = static_cast<sal_uInt16>( i - 6 );
2409 OUString aSuf = read_uInt16s_ToOUString(rSt, n);
2410 sal_Int32 nV = aSuf.toInt32();
2411 if ( ( nV == nVersion ) && ( aPre == "___PPT" ) )
2413 if (!rContentHd.SeekToEndOfRecord(rSt))
2415 break;
2417 ReadDffRecordHeader( rSt, rContentHd );
2418 if ( rContentHd.nRecType == PPT_PST_BinaryTagData )
2420 bRetValue = true;
2421 break;
2426 if (!aProgTagBinaryDataHd.SeekToEndOfRecord(rSt))
2427 break;
2430 if ( !bRetValue )
2431 rSt.Seek( nOldPos );
2432 return bRetValue;
2435 sal_uInt32 SdrPowerPointImport::GetCurrentPageId()
2437 PptSlidePersistList* pList = GetPageList( m_eCurrentPageKind );
2438 if ( pList && m_nCurrentPageNum < pList->size() )
2439 return (*pList)[ m_nCurrentPageNum ].aPersistAtom.nSlideId;
2440 return 0;
2443 bool SdrPowerPointImport::SeekToCurrentPage( DffRecordHeader* pRecHd ) const
2445 bool bRet = false;
2446 PptSlidePersistList* pList = GetPageList( m_eCurrentPageKind );
2447 if ( pList && ( m_nCurrentPageNum < pList->size() ) )
2449 sal_uLong nPersist = (*pList)[ m_nCurrentPageNum ].aPersistAtom.nPsrReference;
2450 if ( nPersist > 0 && nPersist < m_nPersistPtrCnt )
2452 sal_uLong nFPos = m_pPersistPtr[ nPersist ];
2453 if ( nFPos < nStreamLen )
2455 rStCtrl.Seek( nFPos );
2456 if ( pRecHd )
2457 ReadDffRecordHeader( rStCtrl, *pRecHd );
2458 bRet = true;
2462 return bRet;
2465 sal_uInt16 SdrPowerPointImport::GetPageCount( PptPageKind ePageKind ) const
2467 PptSlidePersistList* pList = GetPageList( ePageKind );
2468 if ( pList )
2469 return pList->size();
2470 return 0;
2473 void SdrPowerPointImport::SetPageNum( sal_uInt16 nPageNum, PptPageKind eKind )
2475 m_eCurrentPageKind = eKind;
2476 m_nCurrentPageNum = nPageNum;
2478 m_pPPTStyleSheet = nullptr;
2480 bool bHasMasterPage = true;
2481 sal_uInt16 nMasterIndex = 0;
2483 if ( eKind == PPT_MASTERPAGE )
2484 nMasterIndex = nPageNum;
2485 else
2487 if ( HasMasterPage( nPageNum, eKind ) )
2488 nMasterIndex = GetMasterPageIndex( nPageNum, eKind );
2489 else
2490 bHasMasterPage = false;
2492 if ( bHasMasterPage )
2494 PptSlidePersistList* pPageList = GetPageList( PPT_MASTERPAGE );
2495 if ( pPageList && nMasterIndex < pPageList->size() )
2497 PptSlidePersistEntry* pMasterPersist = &(*pPageList)[ nMasterIndex ];
2498 if (!pMasterPersist->xStyleSheet && pMasterPersist->aSlideAtom.nMasterId)
2500 nMasterIndex = m_pMasterPages->FindPage( pMasterPersist->aSlideAtom.nMasterId );
2501 if ( nMasterIndex != PPTSLIDEPERSIST_ENTRY_NOTFOUND )
2502 pMasterPersist = &(*pPageList)[ nMasterIndex ];
2504 m_pPPTStyleSheet = pMasterPersist->xStyleSheet.get();
2507 if ( !m_pPPTStyleSheet )
2508 m_pPPTStyleSheet = m_pDefaultSheet;
2511 Size SdrPowerPointImport::GetPageSize() const
2513 Size aRet( IsNoteOrHandout( m_nCurrentPageNum ) ? aDocAtom.GetNotesPageSize() : aDocAtom.GetSlidesPageSize() );
2514 Scale( aRet );
2515 // PPT works with units of 576 dpi in any case. To avoid inaccuracies
2516 // I do round the last decimal digit away.
2517 if ( nMapMul > 2 * nMapDiv )
2519 MapUnit eMap = pSdrModel->GetScaleUnit();
2520 bool bInch = IsInch( eMap );
2521 tools::Long nInchMul = 1, nInchDiv = 1;
2522 if ( bInch )
2523 { // temporarily convert size (for rounding it) from inch to metric units
2524 Fraction aFact(GetMapFactor(eMap,MapUnit::Map100thMM).X());
2525 nInchMul = aFact.GetNumerator();
2526 nInchDiv = aFact.GetDenominator();
2527 aRet.setWidth( BigMulDiv( aRet.Width(), nInchMul, nInchDiv ) );
2528 aRet.setHeight( BigMulDiv( aRet.Height(), nInchMul, nInchDiv ) );
2530 aRet.AdjustWidth(5 ); aRet.setWidth( aRet.Width() / 10 ); aRet.setWidth( aRet.Width() * 10 );
2531 aRet.AdjustHeight(5 ); aRet.setHeight( aRet.Height() / 10 ); aRet.setHeight( aRet.Height() * 10 );
2532 if ( bInch )
2534 aRet.setWidth( BigMulDiv( aRet.Width(), nInchDiv, nInchMul ) );
2535 aRet.setHeight( BigMulDiv( aRet.Height(), nInchDiv, nInchMul ) );
2538 return aRet;
2541 bool SdrPowerPointImport::GetColorFromPalette( sal_uInt16 nNum, Color& rColor ) const
2543 if ( m_nPageColorsNum != m_nCurrentPageNum || m_ePageColorsKind != m_eCurrentPageKind )
2545 sal_uInt16 nSlideFlags = 0;
2546 PptSlidePersistList* pPageList = GetPageList( m_eCurrentPageKind );
2547 if ( pPageList && ( m_nCurrentPageNum < pPageList->size() ) )
2549 assert( !pPageList->is_null( m_nCurrentPageNum ) );
2550 const PptSlidePersistEntry& rE = (*pPageList)[ m_nCurrentPageNum ];
2551 nSlideFlags = rE.aSlideAtom.nFlags;
2552 if ( ! ( nSlideFlags & 2 ) )
2553 const_cast<SdrPowerPointImport*>(this)->m_aPageColors = rE.aColorScheme;
2555 if ( nSlideFlags & 2 ) // follow master colorscheme?
2557 PptSlidePersistList* pPageList2 = GetPageList( PPT_MASTERPAGE );
2558 if ( pPageList2 )
2560 PptSlidePersistEntry* pMasterPersist = nullptr;
2561 if ( m_eCurrentPageKind == PPT_MASTERPAGE )
2562 pMasterPersist = &(*pPageList2)[ m_nCurrentPageNum ];
2563 else
2565 if ( HasMasterPage( m_nCurrentPageNum, m_eCurrentPageKind ) )
2567 sal_uInt16 nMasterNum = GetMasterPageIndex( m_nCurrentPageNum, m_eCurrentPageKind );
2568 if ( nMasterNum < pPageList2->size() )
2569 pMasterPersist = &(*pPageList2)[ nMasterNum ];
2572 if ( pMasterPersist )
2574 while( (pMasterPersist->aSlideAtom.nFlags & 2) // it is possible that a masterpage
2575 && pMasterPersist->aSlideAtom.nMasterId ) // itself is following a master colorscheme
2577 auto nOrigMasterId = pMasterPersist->aSlideAtom.nMasterId;
2578 sal_uInt16 nNextMaster = m_pMasterPages->FindPage(nOrigMasterId);
2579 if (nNextMaster == PPTSLIDEPERSIST_ENTRY_NOTFOUND)
2580 break;
2581 pMasterPersist = &(*pPageList2)[ nNextMaster ];
2582 if (pMasterPersist->aSlideAtom.nMasterId == nOrigMasterId)
2584 SAL_WARN("filter.ms", "loop in atom chain");
2585 break;
2588 const_cast<SdrPowerPointImport*>(this)->m_aPageColors = pMasterPersist->aColorScheme;
2592 // register current color scheme
2593 const_cast<SdrPowerPointImport*>(this)->m_nPageColorsNum = m_nCurrentPageNum;
2594 const_cast<SdrPowerPointImport*>(this)->m_ePageColorsKind = m_eCurrentPageKind;
2596 rColor = m_aPageColors.GetColor( nNum );
2597 return true;
2600 bool SdrPowerPointImport::SeekToShape( SvStream& rSt, SvxMSDffClientData* pClientData, sal_uInt32 nId ) const
2602 bool bRet = SvxMSDffManager::SeekToShape( rSt, pClientData, nId );
2603 if (!bRet && pClientData)
2605 ProcessData& rData = *static_cast<ProcessData*>(pClientData);
2606 PptSlidePersistEntry& rPersistEntry = rData.rPersistEntry;
2607 if ( rPersistEntry.ePageKind == PPT_SLIDEPAGE )
2609 if ( HasMasterPage( m_nCurrentPageNum, m_eCurrentPageKind ) )
2611 sal_uInt16 nMasterNum = GetMasterPageIndex( m_nCurrentPageNum, m_eCurrentPageKind );
2612 PptSlidePersistList* pPageList = GetPageList( PPT_MASTERPAGE );
2613 if ( pPageList && ( nMasterNum < pPageList->size() ) )
2615 assert( !pPageList->is_null( nMasterNum ) );
2616 const PptSlidePersistEntry& rPersist = (*pPageList)[ nMasterNum ]; // get the masterpage's persistentry
2617 if ( rPersist.pPresentationObjects )
2619 sal_uInt32 nCurrent(0);
2620 DffRecordList* pCList = maShapeRecords.pCList; // we got a backup of the current position
2621 if ( pCList )
2622 nCurrent = pCList->nCurrent;
2623 if ( const_cast<SdrPowerPointImport*>(this)->maShapeRecords.SeekToContent( rSt, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) )
2625 sal_uInt32 nStreamPos = rSt.Tell();
2626 PPTTextObj aTextObj( rSt, const_cast<SdrPowerPointImport&>(*this), rPersistEntry, nullptr );
2627 if ( aTextObj.Count() || aTextObj.GetOEPlaceHolderAtom() )
2629 sal_uInt32 nShapePos = 0;
2630 switch ( aTextObj.GetInstance() )
2632 case TSS_Type::Title :
2633 nShapePos = rPersist.pPresentationObjects[ int(TSS_Type::PageTitle) ];
2634 break;
2635 case TSS_Type::PageTitle :
2636 nShapePos = rPersist.pPresentationObjects[ int(TSS_Type::PageTitle) ];
2637 break;
2638 case TSS_Type::Subtitle :
2639 case TSS_Type::HalfBody :
2640 case TSS_Type::QuarterBody :
2641 case TSS_Type::Body :
2642 nShapePos = rPersist.pPresentationObjects[ int(TSS_Type::Body) ];
2643 break;
2644 default: break;
2646 if ( nShapePos )
2648 rSt.Seek( nShapePos );
2649 bRet = true;
2652 if ( !bRet )
2653 rSt.Seek( nStreamPos );
2655 if ( pCList ) // restoring
2656 pCList->nCurrent = nCurrent;
2657 const_cast<SdrPowerPointImport*>(this)->maShapeRecords.pCList = pCList;
2663 return bRet;
2666 rtl::Reference<SdrPage> SdrPowerPointImport::MakeBlankPage( bool bMaster ) const
2668 rtl::Reference<SdrPage> pRet = pSdrModel->AllocPage( bMaster );
2669 pRet->SetSize( GetPageSize() );
2671 return pRet;
2674 static void ImportComment10( SvxMSDffManager const & rMan, SvStream& rStCtrl, SdrPage* pPage, DffRecordHeader const & rComment10Hd )
2676 OUString sAuthor;
2677 OUString sText;
2678 OUString sInitials;
2680 sal_Int32 nIndex = 0;
2681 util::DateTime aDateTime;
2682 sal_Int32 nPosX = 0;
2683 sal_Int32 nPosY = 0;
2686 auto nEndRecPos = DffPropSet::SanitizeEndPos(rStCtrl, rComment10Hd.GetRecEndFilePos());
2687 while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nEndRecPos ) )
2689 DffRecordHeader aCommentHd;
2690 ReadDffRecordHeader( rStCtrl, aCommentHd );
2691 switch( aCommentHd.nRecType )
2693 case PPT_PST_CString :
2695 OUString aString = SvxMSDffManager::MSDFFReadZString( rStCtrl,
2696 aCommentHd.nRecLen, true );
2697 switch ( aCommentHd.nRecInstance )
2699 case 0 : sAuthor = aString; break;
2700 case 1 : sText = aString; break;
2701 case 2 : sInitials = aString; break;
2704 break;
2706 case PPT_PST_CommentAtom10 :
2708 sal_uInt16 millisec = 0;
2709 rStCtrl.ReadInt32( nIndex )
2710 .ReadInt16( aDateTime.Year )
2711 .ReadUInt16( aDateTime.Month )
2712 .ReadUInt16( aDateTime.Day ) // DayOfWeek
2713 .ReadUInt16( aDateTime.Day )
2714 .ReadUInt16( aDateTime.Hours )
2715 .ReadUInt16( aDateTime.Minutes )
2716 .ReadUInt16( aDateTime.Seconds )
2717 .ReadUInt16( millisec )
2718 .ReadInt32( nPosX )
2719 .ReadInt32( nPosY );
2721 aDateTime.NanoSeconds = millisec * ::tools::Time::nanoPerMilli;
2723 break;
2725 if (!aCommentHd.SeekToEndOfRecord(rStCtrl))
2726 break;
2728 Point aPosition( nPosX, nPosY );
2729 rMan.Scale( aPosition );
2733 uno::Reference< office::XAnnotationAccess > xAnnotationAccess( pPage->getUnoPage(), UNO_QUERY_THROW );
2734 uno::Reference< office::XAnnotation > xAnnotation( xAnnotationAccess->createAndInsertAnnotation() );
2735 xAnnotation->setPosition( geometry::RealPoint2D( aPosition.X() / 100.0, aPosition.Y() / 100.0 ) );
2736 xAnnotation->setAuthor( sAuthor );
2737 xAnnotation->setDateTime( aDateTime );
2738 xAnnotation->setInitials( sInitials );
2739 uno::Reference< text::XText > xText( xAnnotation->getTextRange() );
2740 xText->setString( sText );
2742 catch( const uno::Exception& )
2749 // be sure not to import masterpages with this method
2750 void SdrPowerPointImport::ImportPage( SdrPage* pRet, const PptSlidePersistEntry* pMasterPersist )
2752 sal_uInt32 nOldPos = rStCtrl.Tell();
2753 PptSlidePersistList* pList = GetPageList( m_eCurrentPageKind );
2754 if ( ( !pList ) || ( pList->size() <= m_nCurrentPageNum ) )
2755 return;
2756 PptSlidePersistEntry& rSlidePersist = (*pList)[ m_nCurrentPageNum ];
2757 if ( rSlidePersist.bStarDrawFiller )
2758 return;
2760 DffRecordHeader aPageHd;
2761 if ( SeekToCurrentPage( &aPageHd ) )
2763 rSlidePersist.xHeaderFooterEntry.reset(new HeaderFooterEntry(pMasterPersist));
2764 ProcessData aProcessData( rSlidePersist, SdPageCapsule(pRet) );
2765 auto nEndRecPos = SanitizeEndPos(rStCtrl, aPageHd.GetRecEndFilePos());
2766 while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nEndRecPos ) )
2768 DffRecordHeader aHd;
2769 ReadDffRecordHeader( rStCtrl, aHd );
2770 switch ( aHd.nRecType )
2772 case PPT_PST_HeadersFooters :
2774 ImportHeaderFooterContainer(aHd, *rSlidePersist.xHeaderFooterEntry);
2776 break;
2778 case PPT_PST_ProgTags :
2780 DffRecordHeader aContentDataHd;
2781 if ( SeekToContentOfProgTag( 10, rStCtrl, aHd, aContentDataHd ) )
2783 DffRecordHeader aComment10Hd;
2784 while( ( rStCtrl.GetError() == ERRCODE_NONE ) && SeekToRec( rStCtrl, PPT_PST_Comment10, aContentDataHd.GetRecEndFilePos(), &aComment10Hd ) )
2786 ImportComment10( *this, rStCtrl, pRet, aComment10Hd );
2787 if (!aComment10Hd.SeekToEndOfRecord(rStCtrl))
2788 break;
2792 break;
2794 case PPT_PST_PPDrawing :
2796 DffRecordHeader aPPDrawHd;
2797 if ( SeekToRec( rStCtrl, DFF_msofbtDgContainer, aHd.GetRecEndFilePos(), &aPPDrawHd ) )
2799 sal_uInt32 nPPDrawOfs = rStCtrl.Tell();
2801 // importing the background object before importing the page
2802 auto nPPEndRecPos = SanitizeEndPos(rStCtrl, aPPDrawHd.GetRecEndFilePos());
2803 while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nPPEndRecPos ) )
2805 DffRecordHeader aEscherObjListHd;
2806 ReadDffRecordHeader( rStCtrl, aEscherObjListHd );
2807 switch ( aEscherObjListHd.nRecType )
2809 case DFF_msofbtSpContainer :
2811 tools::Rectangle aPageSize( Point(), pRet->GetSize() );
2812 if ( rSlidePersist.aSlideAtom.nFlags & 4 ) // follow master background?
2814 if ( HasMasterPage( m_nCurrentPageNum, m_eCurrentPageKind ) )
2816 sal_uInt16 nMasterNum = GetMasterPageIndex( m_nCurrentPageNum, m_eCurrentPageKind );
2817 PptSlidePersistList* pPageList = GetPageList( PPT_MASTERPAGE );
2818 PptSlidePersistEntry* pE = &(*pPageList)[ nMasterNum ];
2819 while( ( pE->aSlideAtom.nFlags & 4 ) && pE->aSlideAtom.nMasterId )
2821 auto nOrigMasterId = pE->aSlideAtom.nMasterId;
2822 sal_uInt16 nNextMaster = m_pMasterPages->FindPage(nOrigMasterId);
2823 if ( nNextMaster == PPTSLIDEPERSIST_ENTRY_NOTFOUND )
2824 break;
2825 else
2826 pE = &(*pPageList)[ nNextMaster ];
2827 if (pE->aSlideAtom.nMasterId == nOrigMasterId)
2829 SAL_WARN("filter.ms", "loop in atom chain");
2830 break;
2833 if ( pE->nBackgroundOffset )
2835 // do not follow master colorscheme?
2836 sal_uInt32 nPos = rStCtrl.Tell();
2837 rStCtrl.Seek( pE->nBackgroundOffset );
2838 rSlidePersist.pBObj = ImportObj( rStCtrl, aProcessData, aPageSize, aPageSize, /*nCalledByGroup*/0, /*pShapeId*/nullptr );
2839 rStCtrl.Seek( nPos );
2843 else
2845 DffRecordHeader aShapeHd;
2846 ReadDffRecordHeader( rStCtrl, aShapeHd );
2847 if ( aShapeHd.nRecType == DFF_msofbtSp )
2849 sal_uInt32 nSpFlags;
2850 rStCtrl.ReadUInt32( nSpFlags ).ReadUInt32( nSpFlags );
2851 if (rStCtrl.good() && ShapeFlag(nSpFlags) & ShapeFlag::Background)
2853 aEscherObjListHd.SeekToBegOfRecord( rStCtrl );
2854 rSlidePersist.pBObj = ImportObj( rStCtrl, aProcessData, aPageSize, aPageSize, /*nCalledByGroup*/0, /*pShapeId*/nullptr );
2859 break;
2861 if ( aEscherObjListHd.nRecType == DFF_msofbtSpContainer )
2862 break;
2863 if (!aEscherObjListHd.SeekToEndOfRecord(rStCtrl))
2864 break;
2867 // now importing page
2868 rStCtrl.Seek( nPPDrawOfs );
2869 auto nHdEndRecPos = SanitizeEndPos(rStCtrl, aPPDrawHd.GetRecEndFilePos());
2870 while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nHdEndRecPos ) )
2872 DffRecordHeader aEscherObjListHd;
2873 ReadDffRecordHeader( rStCtrl, aEscherObjListHd );
2874 switch ( aEscherObjListHd.nRecType )
2876 case DFF_msofbtSpgrContainer :
2878 DffRecordHeader aShapeHd;
2879 if ( SeekToRec( rStCtrl, DFF_msofbtSpContainer, aEscherObjListHd.GetRecEndFilePos(), &aShapeHd ) )
2881 if (!aShapeHd.SeekToEndOfRecord(rStCtrl))
2883 break;
2885 auto nListEndRecPos = SanitizeEndPos(rStCtrl, aEscherObjListHd.GetRecEndFilePos());
2886 while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nListEndRecPos ) )
2888 ReadDffRecordHeader( rStCtrl, aShapeHd );
2889 if ( ( aShapeHd.nRecType == DFF_msofbtSpContainer ) || ( aShapeHd.nRecType == DFF_msofbtSpgrContainer ) )
2891 tools::Rectangle aEmpty;
2892 aShapeHd.SeekToBegOfRecord( rStCtrl );
2893 sal_Int32 nShapeId;
2894 aProcessData.pTableRowProperties.reset();
2895 rtl::Reference<SdrObject> pObj = ImportObj( rStCtrl, aProcessData, aEmpty, aEmpty, 0, &nShapeId );
2896 if ( pObj )
2898 if ( aProcessData.pTableRowProperties )
2899 pObj = CreateTable(pObj.get(), aProcessData.pTableRowProperties.get(), aProcessData.rPersistEntry.xSolverContainer.get());
2901 pRet->NbcInsertObject( pObj.get() );
2903 if( nShapeId )
2904 insertShapeId( nShapeId, pObj.get() );
2907 bool bSuccess = aShapeHd.SeekToEndOfRecord(rStCtrl);
2908 if (!bSuccess)
2909 break;
2913 break;
2915 if ( aEscherObjListHd.nRecType == DFF_msofbtSpgrContainer )
2916 break;
2917 if (!aEscherObjListHd.SeekToEndOfRecord(rStCtrl))
2918 break;
2921 if ( rSlidePersist.pBObj )
2923 // #i99386# transfer the attributes from the temporary BackgroundObject
2924 // to the Page and delete it.
2925 pRet->getSdrPageProperties().ClearItem();
2926 pRet->getSdrPageProperties().PutItemSet(rSlidePersist.pBObj->GetMergedItemSet());
2927 if (rSlidePersist.xSolverContainer)
2929 for (auto & pPtr : rSlidePersist.xSolverContainer->aCList)
2931 // check connections to the group object
2932 if (pPtr->pAObj == rSlidePersist.pBObj.get())
2933 pPtr->pAObj = nullptr;
2934 if (pPtr->pBObj == rSlidePersist.pBObj.get())
2935 pPtr->pBObj = nullptr;
2936 if (pPtr->pCObj == rSlidePersist.pBObj.get())
2937 pPtr->pCObj = nullptr;
2940 rSlidePersist.pBObj.clear();
2944 break;
2946 if (!aHd.SeekToEndOfRecord(rStCtrl))
2947 break;
2949 if (rSlidePersist.xSolverContainer)
2950 SolveSolver(*rSlidePersist.xSolverContainer);
2952 rStCtrl.Seek( nOldPos );
2955 const PptSlideLayoutAtom* SdrPowerPointImport::GetSlideLayoutAtom() const
2957 PptSlidePersistList* pPageList = GetPageList( m_eCurrentPageKind );
2958 if ( pPageList && m_nCurrentPageNum < pPageList->size() )
2960 assert( !pPageList->is_null( m_nCurrentPageNum ) );
2961 return &(*pPageList)[ m_nCurrentPageNum ].aSlideAtom.aLayout;
2963 return nullptr;
2966 bool SdrPowerPointImport::IsNoteOrHandout( sal_uInt16 nPageNum ) const
2968 bool bNote = m_eCurrentPageKind == PPT_NOTEPAGE;
2969 if ( m_eCurrentPageKind == PPT_MASTERPAGE )
2970 bNote = ( nPageNum & 1 ) == 0;
2971 return bNote;
2974 sal_uInt32 SdrPowerPointImport::GetMasterPageId( sal_uInt16 nPageNum, PptPageKind ePageKind ) const
2976 PptSlidePersistList* pPageList = GetPageList( ePageKind );
2977 if ( pPageList && nPageNum < pPageList->size() )
2978 return (*pPageList)[ nPageNum ].aSlideAtom.nMasterId;
2979 return 0;
2982 sal_uInt32 SdrPowerPointImport::GetNotesPageId( sal_uInt16 nPageNum ) const
2984 PptSlidePersistList* pPageList=GetPageList( PPT_SLIDEPAGE );
2985 if ( pPageList && nPageNum < pPageList->size() )
2986 return (*pPageList)[ nPageNum ].aSlideAtom.nNotesId;
2987 return 0;
2990 bool SdrPowerPointImport::HasMasterPage( sal_uInt16 nPageNum, PptPageKind ePageKind ) const
2992 if ( ePageKind == PPT_NOTEPAGE )
2993 return aDocAtom.nNotesMasterPersist != 0;
2994 if ( ePageKind == PPT_MASTERPAGE )
2995 return false;
2996 return GetMasterPageId( nPageNum, ePageKind ) != 0;
2999 sal_uInt16 SdrPowerPointImport::GetMasterPageIndex( sal_uInt16 nPageNum, PptPageKind ePageKind ) const
3001 sal_uInt16 nIdx = 0;
3002 if ( ePageKind == PPT_NOTEPAGE )
3003 return 2;
3004 sal_uInt32 nId = GetMasterPageId( nPageNum, ePageKind );
3005 if (nId && m_pMasterPages)
3007 nIdx = m_pMasterPages->FindPage( nId );
3008 if ( nIdx == PPTSLIDEPERSIST_ENTRY_NOTFOUND )
3009 nIdx = 0;
3011 return nIdx;
3014 rtl::Reference<SdrObject> SdrPowerPointImport::ImportPageBackgroundObject( const SdrPage& rPage, sal_uInt32& nBgFileOffset )
3016 rtl::Reference<SdrObject> pRet;
3017 std::optional<SfxItemSet> pSet;
3018 sal_uInt64 nOldFPos = rStCtrl.Tell(); // remember FilePos for restoring it later
3019 DffRecordHeader aPageHd;
3020 if ( SeekToCurrentPage( &aPageHd ) )
3021 { // and now search for the background attributes of the Page
3022 sal_uLong nPageRecEnd = aPageHd.GetRecEndFilePos();
3023 DffRecordHeader aPPDrawHd;
3024 if ( SeekToRec( rStCtrl, PPT_PST_PPDrawing, nPageRecEnd, &aPPDrawHd ) )
3026 sal_uLong nPPDrawEnd = aPPDrawHd.GetRecEndFilePos();
3027 DffRecordHeader aEscherF002Hd;
3028 if ( SeekToRec( rStCtrl, DFF_msofbtDgContainer, nPPDrawEnd, &aEscherF002Hd ) )
3030 sal_uLong nEscherF002End = aEscherF002Hd.GetRecEndFilePos();
3031 DffRecordHeader aEscherObjectHd;
3032 if ( SeekToRec( rStCtrl, DFF_msofbtSpContainer, nEscherF002End, &aEscherObjectHd ) )
3034 nBgFileOffset = aEscherObjectHd.GetRecBegFilePos();
3035 //sal_uLong nEscherObjectEnd = aEscherObjectHd.GetRecEndFilePos();
3036 //DffRecordHeader aEscherPropertiesHd;
3037 if ( SeekToRec( rStCtrl, DFF_msofbtOPT,nEscherF002End ) )
3039 ReadDffPropSet( rStCtrl, static_cast<DffPropertyReader&>(*this) );
3040 mnFix16Angle = Fix16ToAngle( GetPropertyValue( DFF_Prop_Rotation, 0 ) );
3041 sal_uInt32 nColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff );
3042 pSet.emplace( pSdrModel->GetItemPool() );
3043 DffObjData aObjData( aEscherObjectHd, tools::Rectangle( 0, 0, 28000, 21000 ), 0 );
3044 ApplyAttributes( rStCtrl, *pSet, aObjData );
3045 Color aColor( MSO_CLR_ToColor( nColor ) );
3046 pSet->Put( XFillColorItem( OUString(), aColor ) );
3052 rStCtrl.Seek( nOldFPos ); // restore FilePos
3053 if ( !pSet )
3055 pSet.emplace( pSdrModel->GetItemPool() );
3056 pSet->Put( XFillStyleItem( drawing::FillStyle_NONE ) );
3058 pSet->Put( XLineStyleItem( drawing::LineStyle_NONE ) );
3059 tools::Rectangle aRect(
3060 rPage.GetLeftBorder(),
3061 rPage.GetUpperBorder(),
3062 rPage.GetWidth() - rPage.GetRightBorder(),
3063 rPage.GetHeight() - rPage.GetLowerBorder());
3065 pRet = new SdrRectObj(
3066 *pSdrModel,
3067 aRect);
3069 pRet->SetMergedItemSet(*pSet);
3070 pRet->SetMarkProtect( true );
3071 pRet->SetMoveProtect( true );
3072 pRet->SetResizeProtect( true );
3073 return pRet;
3076 HeaderFooterEntry::HeaderFooterEntry( const PptSlidePersistEntry* pMPE ) :
3077 pMasterPersist ( pMPE ),
3078 nAtom ( 0 )
3080 if ( pMPE )
3082 HeaderFooterEntry* pMHFE = pMPE->xHeaderFooterEntry.get();
3083 if ( pMHFE )
3085 nAtom = pMPE->xHeaderFooterEntry->nAtom;
3086 pPlaceholder[ 0 ] = pMHFE->pPlaceholder[ 0 ];
3087 pPlaceholder[ 1 ] = pMHFE->pPlaceholder[ 1 ];
3088 pPlaceholder[ 2 ] = pMHFE->pPlaceholder[ 2 ];
3089 pPlaceholder[ 3 ] = pMHFE->pPlaceholder[ 3 ];
3094 sal_uInt32 HeaderFooterEntry::IsToDisplay( sal_uInt32 nInstance )
3096 sal_uInt32 nMask = 0;
3097 switch ( nInstance )
3099 case 0 : nMask = 0x010000; break;
3100 case 1 : nMask = 0x100000; break;
3101 case 2 : nMask = 0x200000; break;
3102 case 3 : nMask = 0x080000; break;
3104 return ( nAtom & nMask );
3107 // The following method checks if the slide is using a different colorscheme than
3108 // its master, if this is the fact, then the HeaderFooter must probably be
3109 // imported as real sdrobject. In this case, the return value is the offset to the
3110 // master header footer object, so it can be re-loaded with a different color set
3111 sal_uInt32 HeaderFooterEntry::NeedToImportInstance( const sal_uInt32 nInstance, const PptSlidePersistEntry& rSlidePersist )
3113 sal_uInt32 nRet = 0;
3114 if ( pMasterPersist )
3116 if ( !( rSlidePersist.aSlideAtom.nFlags & 2 ) )
3117 { // not following the master persist, so we have to check if the colors are changed
3118 if ( memcmp( &rSlidePersist.aColorScheme, &pMasterPersist->aColorScheme, 32 ) )
3120 nRet = pMasterPersist->HeaderFooterOfs[ nInstance ];
3124 return nRet;
3127 void SdrEscherImport::ImportHeaderFooterContainer( DffRecordHeader const & rHd, HeaderFooterEntry& rE )
3129 rHd.SeekToContent( rStCtrl );
3130 auto nEndRecPos = SanitizeEndPos(rStCtrl, rHd.GetRecEndFilePos());
3131 while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nEndRecPos ) )
3133 DffRecordHeader aHd;
3134 ReadDffRecordHeader( rStCtrl, aHd );
3135 switch ( aHd.nRecType )
3137 case PPT_PST_HeadersFootersAtom :
3138 rStCtrl.ReadUInt32( rE.nAtom );
3139 break;
3141 case PPT_PST_CString :
3143 if ( aHd.nRecInstance < 4 )
3145 rE.pPlaceholder[ aHd.nRecInstance ] = MSDFFReadZString( rStCtrl,
3146 aHd.nRecLen, true );
3149 break;
3151 if (!aHd.SeekToEndOfRecord(rStCtrl))
3152 break;
3156 PPTBuGraEntry::PPTBuGraEntry( Graphic aGraphic, sal_uInt32 nInst ) :
3157 nInstance ( nInst ),
3158 aBuGra (std::move( aGraphic )) {}
3160 PPTExtParaLevel::PPTExtParaLevel()
3161 : mnExtParagraphMask( 0 )
3162 , mnBuBlip( 0xffff )
3163 , mnHasAnm( 0 )
3164 , mnAnmScheme( 0 )
3165 , mpfPP10Ext( 0 )
3166 , mnExtCharacterMask( 0 )
3167 , mcfPP10Ext( 0 )
3168 , mbSet( false )
3171 SvStream& ReadPPTExtParaLevel( SvStream& rIn, PPTExtParaLevel& rLevel )
3173 rLevel.mbSet = true;
3174 rIn.ReadUInt32( rLevel.mnExtParagraphMask );
3175 if ( rLevel.mnExtParagraphMask & 0x00800000 )
3176 rIn.ReadUInt16( rLevel.mnBuBlip );
3177 if ( rLevel.mnExtParagraphMask & 0x02000000 )
3178 rIn.ReadUInt16( rLevel.mnHasAnm );
3179 if ( rLevel.mnExtParagraphMask & 0x01000000 )
3180 rIn.ReadUInt32( rLevel.mnAnmScheme );
3181 if ( rLevel.mnExtParagraphMask & 0x04000000 )
3182 rIn.ReadUInt32( rLevel.mpfPP10Ext );
3183 rIn.ReadUInt32( rLevel.mnExtCharacterMask );
3184 if ( rLevel.mnExtCharacterMask & 0x100000 )
3185 rIn.ReadUInt32( rLevel.mcfPP10Ext );
3186 return rIn;
3189 bool PPTExtParaProv::GetGraphic( sal_uInt32 nInstance, Graphic& rGraph ) const
3191 bool bRetValue = false;
3192 PPTBuGraEntry* pPtr = nullptr;
3193 if ( nInstance < aBuGraList.size() )
3195 pPtr = aBuGraList[ nInstance ].get();
3196 if ( pPtr->nInstance == nInstance )
3197 bRetValue = true;
3199 if ( !bRetValue )
3201 for (std::unique_ptr<PPTBuGraEntry> const & i : aBuGraList)
3203 pPtr = i.get();
3204 if ( pPtr->nInstance == nInstance )
3206 bRetValue = true;
3207 break;
3211 if ( bRetValue )
3212 rGraph = pPtr->aBuGra;
3213 return bRetValue;
3216 PPTExtParaProv::PPTExtParaProv( SdrPowerPointImport& rMan, SvStream& rSt, const DffRecordHeader* pHd ) :
3217 bStyles ( false )
3219 sal_uInt32 nOldPos = rSt.Tell();
3221 // here we have to get the graphical bullets...
3223 DffRecordHeader aHd;
3224 DffRecordHeader aContentDataHd;
3226 const DffRecordHeader* pListHd = rMan.aDocRecManager.GetRecordHeader( PPT_PST_List );
3227 if( pListHd )
3228 pListHd->SeekToContent( rSt );
3229 if ( pListHd && SdrPowerPointImport::SeekToContentOfProgTag( 9, rSt, *pListHd, aContentDataHd ) )
3231 auto nEndRecPos = DffPropSet::SanitizeEndPos(rSt, aContentDataHd.GetRecEndFilePos());
3232 while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nEndRecPos ) )
3234 ReadDffRecordHeader( rSt, aHd );
3235 switch ( aHd.nRecType )
3237 case PPT_PST_ExtendedBuGraContainer :
3239 auto nHdEndRecPos = DffPropSet::SanitizeEndPos(rSt, aHd.GetRecEndFilePos());
3240 while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nHdEndRecPos ) )
3242 DffRecordHeader aBuGraAtomHd;
3243 ReadDffRecordHeader( rSt, aBuGraAtomHd );
3244 if ( aBuGraAtomHd.nRecType == PPT_PST_ExtendedBuGraAtom )
3246 sal_uInt16 nType;
3247 rSt.ReadUInt16( nType );
3248 Graphic aGraphic;
3249 if ( SvxMSDffManager::GetBLIPDirect( rSt, aGraphic ) )
3251 sal_uInt32 nInstance = aBuGraAtomHd.nRecInstance;
3252 PPTBuGraEntry* pBuGra = new PPTBuGraEntry( std::move(aGraphic), nInstance );
3253 size_t n = 0;
3254 size_t nBuGraCount = aBuGraList.size();
3255 if ( nBuGraCount )
3257 if ( aBuGraList[ nBuGraCount - 1 ]->nInstance < nInstance )
3258 n = nBuGraCount;
3259 else
3260 { // maybe the instances are not sorted, we sort it
3261 for ( n = 0; n < nBuGraCount; n++ )
3262 { // sorting fields ( hi >> lo )
3263 if ( aBuGraList[ n ]->nInstance < nInstance )
3264 break;
3268 if ( n < nBuGraCount ) {
3269 aBuGraList.emplace( aBuGraList.begin() + n, pBuGra );
3270 } else {
3271 aBuGraList.emplace_back( pBuGra );
3274 #ifdef DBG_UTIL
3275 else OSL_FAIL( "PPTExParaProv::PPTExParaProv - bullet graphic is not valid (SJ)" );
3276 #endif
3278 #ifdef DBG_UTIL
3279 else OSL_FAIL( "PPTExParaProv::PPTExParaProv - unknown atom interpreting the PPT_PST_ExtendedBuGraContainer (SJ)" );
3280 #endif
3281 if (!aBuGraAtomHd.SeekToEndOfRecord(rSt))
3282 break;
3285 break;
3287 case PPT_PST_ExtendedPresRuleContainer :
3288 aExtendedPresRules.Consume( rSt, aHd.GetRecEndFilePos() );
3289 break;
3290 #ifdef DBG_UTIL
3291 default :
3292 OSL_FAIL( "PPTExParaProv::PPTExParaProv - unknown atom reading ppt2000 num rules (SJ)" );
3293 break;
3294 case PPT_PST_MasterText : // first seen in: ms-tt02.ppt
3295 case PPT_PST_SrKinsoku :
3296 case PPT_PST_TextDefaults9Atom :
3297 case PPT_PST_PresentationAdvisorFlags9Atom :
3298 case PPT_PST_HtmlDocInfo9Atom :
3299 case PPT_PST_GridSpacing10Atom :
3300 case PPT_PST_CommentIndex10 :
3301 case PPT_PST_DocToolbarStates10Atom :
3302 break;
3303 #endif
3305 if (!aHd.SeekToEndOfRecord(rSt))
3306 break;
3310 if ( pHd && SdrPowerPointImport::SeekToContentOfProgTag( 9, rSt, *pHd, aContentDataHd ) )
3311 { // get the extended paragraph styles on mainmaster ( graphical bullets, num ruling ... )
3312 auto nEndRecPos = DffPropSet::SanitizeEndPos(rSt, aContentDataHd.GetRecEndFilePos());
3313 while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nEndRecPos ) )
3315 ReadDffRecordHeader( rSt, aHd );
3316 switch ( aHd.nRecType )
3318 case PPT_PST_ExtendedParagraphMasterAtom :
3320 if ( aHd.nRecInstance < PPT_STYLESHEETENTRIES )
3322 sal_uInt16 nDepth = 0, i = 0;
3323 rSt.ReadUInt16(nDepth);
3324 nDepth = std::min<sal_uInt16>(nDepth, nMaxPPTLevels);
3325 auto nHdEndRecPos = DffPropSet::SanitizeEndPos(rSt, aHd.GetRecEndFilePos());
3326 while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nHdEndRecPos ) && ( i < nDepth ) )
3328 bStyles = true;
3329 ReadPPTExtParaLevel( rSt, aExtParaSheet[ static_cast<TSS_Type>(aHd.nRecInstance) ].aExtParaLevel[ i++ ] );
3331 #ifdef DBG_UTIL
3332 if ( rSt.Tell() != aHd.GetRecEndFilePos() )
3333 OSL_FAIL( "PPTExParaProv::PPTExParaProv - error reading PPT_PST_ExtendedParagraphMasterAtom (SJ)" );
3334 #endif
3336 #ifdef DBG_UTIL
3337 else OSL_FAIL( "PPTExParaProv::PPTExParaProv - instance out of range (SJ)" );
3338 #endif
3340 break;
3341 default :
3342 OSL_FAIL( "PPTExParaProv::PPTExParaProv - unknown atom, assuming PPT_PST_ExtendedParagraphMasterAtom (SJ)" );
3343 break;
3344 case PPT_PST_HashCodeAtom :
3345 case PPT_PST_BuildList :
3346 case PPT_PST_SlideFlags10Atom :
3347 case PPT_PST_SlideTime10Atom :
3348 case 0xf144 :
3349 break;
3351 if (!aHd.SeekToEndOfRecord(rSt))
3352 break;
3355 rSt.Seek( nOldPos );
3358 PPTExtParaProv::~PPTExtParaProv()
3362 PPTNumberFormatCreator::PPTNumberFormatCreator( std::unique_ptr<PPTExtParaProv> pParaProv )
3363 : nIsBullet(0)
3364 , nBulletChar(0)
3365 , nBulletFont(0)
3366 , nBulletHeight(0)
3367 , nBulletColor(0)
3368 , nTextOfs(0)
3369 , nBulletOfs(0)
3370 , pExtParaProv(std::move(pParaProv))
3374 PPTNumberFormatCreator::~PPTNumberFormatCreator()
3378 bool PPTNumberFormatCreator::ImplGetExtNumberFormat( SdrPowerPointImport const & rManager,
3379 SvxNumberFormat& rNumberFormat, sal_uInt32 nLevel, TSS_Type nInstance, TSS_Type nDestinationInstance,
3380 std::optional< sal_Int16 >& rStartNumbering, sal_uInt32 nFontHeight, PPTParagraphObj const * pPara )
3382 bool bHardAttribute = ( nDestinationInstance == TSS_Type::Unknown );
3384 sal_uInt32 nBuFlags = 0;
3385 sal_uInt16 nHasAnm = 0;
3386 sal_uInt32 nAnmScheme = 0xFFFF0003;
3387 sal_uInt16 nBuBlip = 0xffff;
3389 const PPTExtParaProv* pParaProv = pExtParaProv.get();
3390 if ( !pExtParaProv )
3391 pParaProv = pPara ? pPara->mrStyleSheet.pExtParaProv.get()
3392 : rManager.m_pPPTStyleSheet->pExtParaProv.get();
3393 if ( pPara )
3395 nBuFlags = pPara->mxParaSet->mnExtParagraphMask;
3396 if ( nBuFlags )
3398 if ( nBuFlags & 0x00800000 )
3399 nBuBlip = pPara->mxParaSet->mnBuBlip;
3400 if ( nBuFlags & 0x01000000 )
3401 nAnmScheme = pPara->mxParaSet->mnAnmScheme;
3402 if ( nBuFlags & 0x02000000 )
3403 nHasAnm = pPara->mxParaSet->mnHasAnm;
3404 bHardAttribute = true;
3408 if ( ( nBuFlags & 0x03800000 ) != 0x03800000 ) // merge style sheet
3410 // we have to read the master attributes
3411 if (pParaProv && nLevel < nMaxPPTLevels)
3413 if ( pParaProv->bStyles )
3415 const PPTExtParaLevel& rLev = pParaProv->aExtParaSheet[ nInstance ].aExtParaLevel[ nLevel ];
3416 if ( rLev.mbSet )
3418 sal_uInt32 nMaBuFlags = rLev.mnExtParagraphMask;
3420 if ( (!( nBuFlags & 0x00800000)) && ( nMaBuFlags & 0x00800000 ) )
3422 if (!( nBuFlags & 0x02000000)) // if there is a BuStart without BuInstance,
3423 nBuBlip = rLev.mnBuBlip; // then there is no graphical Bullet possible
3425 if ( (!( nBuFlags & 0x01000000)) && ( nMaBuFlags & 0x01000000 ) )
3426 nAnmScheme = rLev.mnAnmScheme;
3427 if ( (!( nBuFlags & 0x02000000)) && ( nMaBuFlags & 0x02000000 ) )
3428 nHasAnm = rLev.mnHasAnm;
3429 nBuFlags |= nMaBuFlags;
3434 if ( nBuBlip != 0xffff ) // set graphical bullet
3436 Graphic aGraphic;
3437 if ( pParaProv && pParaProv->GetGraphic( nBuBlip, aGraphic ) )
3439 SvxBrushItem aBrush( aGraphic, GPOS_MM, SID_ATTR_BRUSH );
3440 rNumberFormat.SetGraphicBrush( &aBrush );
3441 sal_uInt32 nHeight = static_cast<sal_uInt32>( static_cast<double>(nFontHeight) * 0.2540 * nBulletHeight + 0.5 );
3442 Size aPrefSize( aGraphic.GetPrefSize() );
3443 sal_uInt32 nWidth;
3444 if (aPrefSize.Height())
3445 nWidth = ( nHeight * aPrefSize.Width() ) / aPrefSize.Height();
3446 else
3447 nWidth = 0;
3448 rNumberFormat.SetGraphicSize( Size( nWidth, nHeight ) );
3449 rNumberFormat.SetNumberingType ( SVX_NUM_BITMAP );
3452 else if ( nHasAnm )
3454 switch( static_cast< sal_uInt16 >( nAnmScheme ) )
3456 default :
3457 case 0 :
3459 rNumberFormat.SetNumberingType( SVX_NUM_CHARS_LOWER_LETTER );
3460 rNumberFormat.SetListFormat("", ".", nLevel);
3462 break;
3463 case 1 :
3465 rNumberFormat.SetNumberingType( SVX_NUM_CHARS_UPPER_LETTER );
3466 rNumberFormat.SetListFormat("", ".", nLevel);
3468 break;
3469 case 2 :
3471 rNumberFormat.SetNumberingType( SVX_NUM_ARABIC );
3472 rNumberFormat.SetListFormat("", ")", nLevel);
3474 break;
3475 case 3 :
3477 rNumberFormat.SetNumberingType( SVX_NUM_ARABIC );
3478 rNumberFormat.SetListFormat("", ".", nLevel);
3480 break;
3481 case 4 :
3483 rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_LOWER );
3484 rNumberFormat.SetListFormat("(", ")", nLevel);
3486 break;
3487 case 5 :
3489 rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_LOWER );
3490 rNumberFormat.SetListFormat("", ")", nLevel);
3492 break;
3493 case 6 :
3495 rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_LOWER );
3496 rNumberFormat.SetListFormat("", ".", nLevel);
3498 break;
3499 case 7 :
3501 rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_UPPER );
3502 rNumberFormat.SetListFormat("", ".", nLevel);
3504 break;
3505 case 8 :
3507 rNumberFormat.SetNumberingType( SVX_NUM_CHARS_LOWER_LETTER );
3508 rNumberFormat.SetListFormat("(", ")", nLevel);
3510 break;
3511 case 9 :
3513 rNumberFormat.SetNumberingType( SVX_NUM_CHARS_LOWER_LETTER );
3514 rNumberFormat.SetListFormat("", ")", nLevel);
3516 break;
3517 case 10 :
3519 rNumberFormat.SetNumberingType( SVX_NUM_CHARS_UPPER_LETTER );
3520 rNumberFormat.SetListFormat("(", ")", nLevel);
3522 break;
3523 case 11 :
3525 rNumberFormat.SetNumberingType( SVX_NUM_CHARS_UPPER_LETTER );
3526 rNumberFormat.SetListFormat("", ")", nLevel);
3528 break;
3529 case 12 :
3531 rNumberFormat.SetNumberingType( SVX_NUM_ARABIC );
3532 rNumberFormat.SetListFormat("(", ")", nLevel);
3534 break;
3535 case 13 :
3537 rNumberFormat.SetNumberingType( SVX_NUM_ARABIC );
3539 break;
3540 case 14 :
3542 rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_UPPER );
3543 rNumberFormat.SetListFormat("(", ")", nLevel);
3545 break;
3546 case 15 :
3548 rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_UPPER );
3549 rNumberFormat.SetListFormat("", ")", nLevel);
3551 break;
3552 case 16: // Simplified Chinese.
3554 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_UPPER_ZH );
3556 break;
3557 case 17: // Simplified Chinese with single-byte period.
3559 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_UPPER_ZH );
3560 rNumberFormat.SetListFormat("", ".", nLevel);
3562 break;
3563 case 18: // Double byte circle numbers.
3564 case 19: // Wingdings white circle numbers.
3565 case 20: // Wingdings black circle numbers.
3567 rNumberFormat.SetNumberingType( SVX_NUM_CIRCLE_NUMBER );
3569 break;
3570 case 21: // Traditional Chinese.
3572 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_UPPER_ZH_TW );
3574 break;
3575 case 22: // Traditional Chinese with single-byte period.
3577 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_UPPER_ZH_TW );
3578 rNumberFormat.SetListFormat("", ".", nLevel);
3580 break;
3581 case 25: // Bidi Hebrew 2 with ANSI minus symbol.
3583 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_HEBREW );
3584 rNumberFormat.SetListFormat("", "-", nLevel);
3586 break;
3587 case 26: // Japanese/Korean.
3589 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_LOWER_ZH );
3591 break;
3592 case 27: // Japanese/Korean with single-byte period.
3594 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_LOWER_ZH );
3595 rNumberFormat.SetListFormat("", ".", nLevel);
3597 break;
3598 case 28: // Double-byte Arabic numbers.
3600 rNumberFormat.SetNumberingType( SVX_NUM_FULL_WIDTH_ARABIC );
3602 break;
3603 case 29: // Double-byte Arabic numbers with double-byte period.
3605 rNumberFormat.SetNumberingType( SVX_NUM_FULL_WIDTH_ARABIC );
3606 rNumberFormat.SetListFormat("", OUString(u'\xff0e'), nLevel);
3608 break;
3609 case 38: // Japanese with double-byte period.
3611 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_LOWER_ZH ); // No such type. Instead with Lower Chinese Number
3612 rNumberFormat.SetListFormat("", OUString(u'\xff0e'), nLevel);
3614 break;
3616 rStartNumbering = std::optional< sal_Int16 >( nAnmScheme >> 16 );
3617 sal_Int16 nBuStart = *rStartNumbering;
3618 //The Seventh bit of nBuFlags that specifies whether fBulletHasAutoNumber exists,
3619 //and fBulletHasAutoNumber that specifies whether this paragraph has an automatic numbering scheme.
3620 if ( ( nBuFlags & 0x02000000 ) && ( nBuStart != -1 ))
3622 rNumberFormat.SetStart( static_cast<sal_uInt16>(nBuStart) );
3625 return bHardAttribute;
3628 void PPTNumberFormatCreator::GetNumberFormat( SdrPowerPointImport const & rManager, SvxNumberFormat& rNumberFormat, sal_uInt32 nLevel, const PPTParaLevel& rParaLevel, const PPTCharLevel& rCharLevel, TSS_Type nInstance )
3630 nIsBullet = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BulletOn ) ) != 0 ? 1 : 0;
3631 nBulletChar = rParaLevel.mnBulletChar;
3633 bool bBuHardFont;
3634 bBuHardFont = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardFont ) ) != 0;
3635 if ( bBuHardFont )
3636 nBulletFont = rParaLevel.mnBulletFont;
3637 else
3638 nBulletFont = rCharLevel.mnFont;
3639 nBulletHeight = rParaLevel.mnBulletHeight;
3640 nBulletColor = rParaLevel.mnBulletColor;
3641 nTextOfs = rParaLevel.mnTextOfs;
3642 nBulletOfs = rParaLevel.mnBulletOfs;
3644 std::optional< sal_Int16 > oStartNumbering;
3645 ImplGetExtNumberFormat( rManager, rNumberFormat, nLevel, nInstance, TSS_Type::Unknown, oStartNumbering, rCharLevel.mnFontHeight, nullptr );
3646 if ( ( rNumberFormat.GetNumberingType() != SVX_NUM_BITMAP ) && ( nBulletHeight > 0x7fff ) )
3647 nBulletHeight = rCharLevel.mnFontHeight ? ((- static_cast<sal_Int16>(nBulletHeight)) * 100 ) / rCharLevel.mnFontHeight : 100;
3648 ImplGetNumberFormat( rManager, rNumberFormat );
3649 switch ( rNumberFormat.GetNumberingType() )
3651 case SVX_NUM_CHARS_UPPER_LETTER :
3652 case SVX_NUM_CHARS_LOWER_LETTER :
3653 case SVX_NUM_ROMAN_UPPER :
3654 case SVX_NUM_ROMAN_LOWER :
3655 case SVX_NUM_ARABIC :
3656 case SVX_NUM_CHARS_UPPER_LETTER_N :
3657 case SVX_NUM_CHARS_LOWER_LETTER_N :
3659 sal_uInt32 nFont = rCharLevel.mnFont;
3660 const PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nFont );
3661 if ( pFontEnityAtom )
3663 vcl::Font aFont;
3664 aFont.SetCharSet( pFontEnityAtom->eCharSet );
3665 aFont.SetFamilyName( pFontEnityAtom->aName );
3666 aFont.SetFamily( pFontEnityAtom->eFamily );
3667 aFont.SetPitch( pFontEnityAtom->ePitch );
3668 rNumberFormat.SetBulletFont( &aFont );
3671 break;
3672 default: break;
3676 bool PPTNumberFormatCreator::GetNumberFormat( SdrPowerPointImport const & rManager, SvxNumberFormat& rNumberFormat, PPTParagraphObj* pParaObj,
3677 TSS_Type nDestinationInstance, std::optional< sal_Int16 >& rStartNumbering )
3679 sal_uInt32 nHardCount = 0;
3680 nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletOn, nIsBullet, nDestinationInstance ) ? 1 : 0;
3681 nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletChar, nBulletChar, nDestinationInstance ) ? 1 : 0;
3682 nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletFont, nBulletFont, nDestinationInstance ) ? 1 : 0;
3683 nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletHeight, nBulletHeight, nDestinationInstance ) ? 1 : 0;
3684 nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletColor, nBulletColor, nDestinationInstance ) ? 1 : 0;
3685 nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_TextOfs, nTextOfs, nDestinationInstance ) ? 1 : 0;
3686 nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletOfs, nBulletOfs, nDestinationInstance ) ? 1 : 0;
3688 if ( nIsBullet )
3689 rNumberFormat.SetNumberingType( SVX_NUM_CHAR_SPECIAL );
3691 sal_uInt32 nFontHeight = 24;
3692 PPTPortionObj* pPtr = pParaObj->First();
3693 if ( pPtr )
3694 pPtr->GetAttrib( PPT_CharAttr_FontHeight, nFontHeight, nDestinationInstance );
3695 if ( nIsBullet )
3696 nHardCount += ImplGetExtNumberFormat( rManager, rNumberFormat, pParaObj->mxParaSet->mnDepth,
3697 pParaObj->mnInstance, nDestinationInstance, rStartNumbering, nFontHeight, pParaObj ) ? 1 : 0;
3699 if ( rNumberFormat.GetNumberingType() != SVX_NUM_BITMAP )
3700 pParaObj->UpdateBulletRelSize( nBulletHeight );
3701 if ( nHardCount )
3703 ImplGetNumberFormat( rManager, rNumberFormat );
3704 switch ( rNumberFormat.GetNumberingType() )
3706 case SVX_NUM_CHARS_UPPER_LETTER :
3707 case SVX_NUM_CHARS_LOWER_LETTER :
3708 case SVX_NUM_ROMAN_UPPER :
3709 case SVX_NUM_ROMAN_LOWER :
3710 case SVX_NUM_ARABIC :
3711 case SVX_NUM_CHARS_UPPER_LETTER_N :
3712 case SVX_NUM_CHARS_LOWER_LETTER_N :
3714 if ( pPtr )
3716 sal_uInt32 nFont;
3717 pPtr->GetAttrib( PPT_CharAttr_Font, nFont, nDestinationInstance );
3718 const PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nFont );
3719 if ( pFontEnityAtom )
3721 vcl::Font aFont;
3722 aFont.SetCharSet( pFontEnityAtom->eCharSet );
3723 aFont.SetFamilyName( pFontEnityAtom->aName );
3724 aFont.SetFamily( pFontEnityAtom->eFamily );
3725 aFont.SetPitch( pFontEnityAtom->ePitch );
3726 rNumberFormat.SetBulletFont( &aFont );
3730 break;
3731 default: break;
3734 return nHardCount != 0;
3737 void PPTNumberFormatCreator::ImplGetNumberFormat( SdrPowerPointImport const & rManager, SvxNumberFormat& rNumberFormat )
3739 vcl::Font aFont;
3740 const PptFontEntityAtom* pAtom = rManager.GetFontEnityAtom( nBulletFont );
3741 if ( pAtom )
3743 rtl_TextEncoding eCharSet( pAtom->eCharSet );
3744 aFont.SetFamilyName( pAtom->aName );
3745 aFont.SetCharSet( eCharSet );
3746 aFont.SetFamily( pAtom->eFamily );
3747 aFont.SetPitch( pAtom->ePitch );
3749 Color aCol( rManager.MSO_TEXT_CLR_ToColor( nBulletColor ) );
3750 aFont.SetColor( aCol );
3752 sal_uInt16 nBuChar = static_cast<sal_uInt16>(nBulletChar);
3753 if ( aFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
3755 nBuChar &= 0x00ff;
3756 nBuChar |= 0xf000;
3758 rNumberFormat.SetBulletFont( &aFont );
3759 rNumberFormat.SetBulletChar( nBuChar );
3760 rNumberFormat.SetBulletRelSize( static_cast<sal_uInt16>(nBulletHeight) );
3761 rNumberFormat.SetBulletColor( aCol );
3762 sal_uInt32 nAbsLSpace = convertMasterUnitToMm100(nTextOfs);
3763 sal_uInt32 nFirstLineOffset = nAbsLSpace - convertMasterUnitToMm100(nBulletOfs);
3764 rNumberFormat.SetAbsLSpace( nAbsLSpace );
3765 rNumberFormat.SetFirstLineOffset( -static_cast<sal_Int32>(nFirstLineOffset) );
3768 PPTCharSheet::PPTCharSheet( TSS_Type nInstance )
3770 sal_uInt32 nColor = PPT_COLSCHEME_TEXT_UND_ZEILEN;
3771 sal_uInt16 nFontHeight(0);
3772 switch ( nInstance )
3774 case TSS_Type::PageTitle :
3775 case TSS_Type::Title :
3777 nColor = PPT_COLSCHEME_TITELTEXT;
3778 nFontHeight = 44;
3780 break;
3781 case TSS_Type::Body :
3782 case TSS_Type::Subtitle :
3783 case TSS_Type::HalfBody :
3784 case TSS_Type::QuarterBody :
3785 nFontHeight = 32;
3786 break;
3787 case TSS_Type::Notes :
3788 nFontHeight = 12;
3789 break;
3790 case TSS_Type::Unused :
3791 case TSS_Type::TextInShape :
3792 nFontHeight = 24;
3793 break;
3794 default: break;
3796 for (PPTCharLevel & nDepth : maCharLevel)
3798 nDepth.mnFlags = 0;
3799 nDepth.mnFont = 0;
3800 nDepth.mnAsianOrComplexFont = 0xffff;
3801 nDepth.mnFontHeight = nFontHeight;
3802 nDepth.mnFontColor = nColor;
3803 nDepth.mnFontColorInStyleSheet = Color( static_cast<sal_uInt8>(nColor), static_cast<sal_uInt8>( nColor >> 8 ), static_cast<sal_uInt8>( nColor >> 16 ) );
3804 nDepth.mnEscapement = 0;
3808 void PPTCharSheet::Read( SvStream& rIn, sal_uInt32 nLevel)
3810 // character attributes
3811 sal_uInt32 nCMask(0);
3812 sal_uInt16 nVal16;
3813 rIn.ReadUInt32(nCMask);
3815 if ( nCMask & 0x0000FFFF )
3817 sal_uInt16 nBitAttr(0);
3818 maCharLevel[ nLevel ].mnFlags &= ~static_cast<sal_uInt16>(nCMask);
3819 rIn.ReadUInt16( nBitAttr ); // Bit attributes (bold, underlined, ...)
3820 maCharLevel[ nLevel ].mnFlags |= nBitAttr;
3822 if ( nCMask & ( 1 << PPT_CharAttr_Font ) ) // 0x00010000
3823 rIn.ReadUInt16( maCharLevel[ nLevel ].mnFont );
3824 if ( nCMask & ( 1 << PPT_CharAttr_AsianOrComplexFont ) ) // 0x00200000
3825 rIn.ReadUInt16( maCharLevel[ nLevel ].mnAsianOrComplexFont );
3826 if ( nCMask & ( 1 << PPT_CharAttr_ANSITypeface ) ) // 0x00400000
3827 rIn.ReadUInt16( nVal16 );
3828 if ( nCMask & ( 1 << PPT_CharAttr_Symbol ) ) // 0x00800000
3829 rIn.ReadUInt16( nVal16 );
3830 if ( nCMask & ( 1 << PPT_CharAttr_FontHeight ) ) // 0x00020000
3831 rIn.ReadUInt16( maCharLevel[ nLevel ].mnFontHeight );
3832 if ( nCMask & ( 1 << PPT_CharAttr_FontColor ) ) // 0x00040000
3834 rIn.ReadUInt32( maCharLevel[ nLevel ].mnFontColor );
3835 if( ! (maCharLevel[ nLevel ].mnFontColor & 0xff000000 ) )
3836 maCharLevel[ nLevel ].mnFontColor = PPT_COLSCHEME_HINTERGRUND;
3838 if ( nCMask & ( 1 << PPT_CharAttr_Escapement ) ) // 0x00080000
3839 rIn.ReadUInt16( maCharLevel[ nLevel ].mnEscapement );
3840 if ( nCMask & 0x00100000 ) // 0x00100000
3841 rIn.ReadUInt16( nVal16 );
3843 nCMask >>= 24;
3844 while( nCMask )
3846 if ( nCMask & 1 )
3848 OSL_FAIL( "PPTCharSheet::Read - unknown attribute, send me this document (SJ)" );
3849 rIn.ReadUInt16( nVal16 );
3851 nCMask >>= 1;
3855 PPTParaSheet::PPTParaSheet( TSS_Type nInstance )
3857 sal_uInt16 nBuFlags = 0;
3858 sal_uInt32 nBulletColor = 0x8000000;
3859 sal_uInt16 nUpperDist = 0;
3861 switch ( nInstance )
3863 case TSS_Type::PageTitle :
3864 case TSS_Type::Title :
3865 nBulletColor = PPT_COLSCHEME_TITELTEXT;
3866 break;
3867 case TSS_Type::Body :
3868 case TSS_Type::Subtitle :
3869 case TSS_Type::HalfBody :
3870 case TSS_Type::QuarterBody :
3872 nBuFlags = 1;
3873 nUpperDist = 0x14;
3875 break;
3876 case TSS_Type::Notes :
3877 nUpperDist = 0x1e;
3878 break;
3879 default: break;
3881 for (PPTParaLevel & i : maParaLevel)
3883 i.mnBuFlags = nBuFlags;
3884 i.mnBulletChar = 0x2022;
3885 i.mnBulletFont = 0;
3886 i.mnBulletHeight = 100;
3887 i.mnBulletColor = nBulletColor;
3888 i.mnAdjust = 0;
3889 i.mnLineFeed = 100;
3890 i.mnLowerDist = 0;
3891 i.mnUpperDist = nUpperDist;
3892 i.mnTextOfs = 0;
3893 i.mnBulletOfs = 0;
3894 i.mnDefaultTab = 0x240;
3895 i.mnAsianLineBreak = 0;
3896 i.mnBiDi = 0;
3900 void PPTParaSheet::Read( SdrPowerPointImport const &
3901 #ifdef DBG_UTIL
3902 rManager
3903 #endif
3904 , SvStream& rIn
3905 , sal_uInt32 nLevel, bool bFirst )
3907 // paragraph attributes
3908 sal_uInt32 nPMask(0);
3909 rIn.ReadUInt32(nPMask);
3911 sal_uInt16 nMask16 = static_cast<sal_uInt16>(nPMask) & 0xf;
3912 if ( nMask16 )
3914 sal_uInt16 nVal16(0);
3915 rIn.ReadUInt16( nVal16 );
3916 maParaLevel[ nLevel ].mnBuFlags &=~ nMask16;
3917 nVal16 &= nMask16;
3918 maParaLevel[ nLevel ].mnBuFlags |= nVal16;
3920 if ( nPMask & 0x0080 )
3921 rIn.ReadUInt16( maParaLevel[ nLevel ].mnBulletChar );
3922 if ( nPMask & 0x0010 )
3923 rIn.ReadUInt16( maParaLevel[ nLevel ].mnBulletFont );
3924 if ( nPMask & 0x0040 )
3926 sal_uInt16 nVal16(0);
3927 rIn.ReadUInt16( nVal16 );
3928 maParaLevel[ nLevel ].mnBulletHeight = nVal16;
3930 if ( nPMask & 0x0020 )
3932 sal_uInt32 nVal32(0);
3933 rIn.ReadUInt32(nVal32);
3934 maParaLevel[ nLevel ].mnBulletColor = nVal32;
3936 if ( bFirst )
3938 if ( nPMask & 0xF00 )
3940 // AbsJust!
3941 sal_uInt16 nVal16(0);
3942 rIn.ReadUInt16( nVal16 );
3943 maParaLevel[ nLevel ].mnAdjust = nVal16 & 3;
3945 if ( nPMask & 0x1000 )
3946 rIn.ReadUInt16( maParaLevel[ nLevel ].mnLineFeed );
3947 if ( nPMask & 0x2000 )
3948 rIn.ReadUInt16( maParaLevel[ nLevel ].mnUpperDist );
3949 if ( nPMask & 0x4000 )
3950 rIn.ReadUInt16( maParaLevel[ nLevel ].mnLowerDist );
3951 if ( nPMask & 0x8000 )
3952 rIn.ReadUInt16( maParaLevel[ nLevel ].mnTextOfs );
3953 if ( nPMask & 0x10000 )
3954 rIn.ReadUInt16( maParaLevel[ nLevel ].mnBulletOfs );
3955 if ( nPMask & 0x20000 )
3956 rIn.ReadUInt16( maParaLevel[ nLevel ].mnDefaultTab );
3957 if ( nPMask & 0x200000 )
3959 sal_uInt16 nVal16;
3960 sal_uInt32 nVal32;
3961 // number of tabulators
3962 rIn.ReadUInt16( nVal16 );
3963 if (!rIn.good() || rIn.remainingSize() / sizeof(nVal32) < nVal16)
3964 return;
3965 for (sal_uInt16 i = 0; i < nVal16; ++i)
3966 rIn.ReadUInt32( nVal32 ); // reading the tabulators
3968 if ( nPMask & 0x40000 )
3970 sal_uInt16 nVal16;
3971 rIn.ReadUInt16( nVal16 );
3973 if ( nPMask & 0x80000 )
3974 rIn.ReadUInt16( maParaLevel[ nLevel ].mnAsianLineBreak );
3975 if ( nPMask & 0x100000 )
3976 rIn.ReadUInt16( maParaLevel[ nLevel ].mnBiDi );
3978 else
3980 if ( nPMask & 0x800 )
3982 sal_uInt16 nVal16(0);
3983 rIn.ReadUInt16( nVal16 );
3984 maParaLevel[ nLevel ].mnAdjust = nVal16 & 3;
3986 if ( nPMask & 0x1000 )
3987 rIn.ReadUInt16( maParaLevel[ nLevel ].mnLineFeed );
3988 if ( nPMask & 0x2000 )
3989 rIn.ReadUInt16( maParaLevel[ nLevel ].mnUpperDist );
3990 if ( nPMask & 0x4000 )
3991 rIn.ReadUInt16( maParaLevel[ nLevel ].mnLowerDist );
3992 if ( nPMask & 0x8000 )
3994 sal_uInt16 nVal16;
3995 rIn.ReadUInt16( nVal16 );
3997 if ( nPMask & 0x100 )
3998 rIn.ReadUInt16( maParaLevel[ nLevel ].mnTextOfs );
3999 if ( nPMask & 0x200 )
4001 sal_uInt16 nVal16;
4002 rIn.ReadUInt16( nVal16 );
4004 if ( nPMask & 0x400 )
4005 rIn.ReadUInt16( maParaLevel[ nLevel ].mnBulletOfs );
4006 if ( nPMask & 0x10000 )
4008 sal_uInt16 nVal16;
4009 rIn.ReadUInt16( nVal16 );
4011 if ( nPMask & 0xe0000 )
4013 sal_uInt16 nFlagsToModifyMask = static_cast<sal_uInt16>( ( nPMask >> 17 ) & 7 );
4014 sal_uInt16 nVal16(0);
4015 rIn.ReadUInt16( nVal16 );
4016 // bits that are not involved to zero
4017 nVal16 &= nFlagsToModifyMask;
4018 // bits that are to change to zero
4019 maParaLevel[ nLevel ].mnAsianLineBreak &=~nFlagsToModifyMask;
4020 // now set the corresponding bits
4021 maParaLevel[ nLevel ].mnAsianLineBreak |= nVal16;
4023 if ( nPMask & 0x100000 )
4025 sal_uInt16 nVal16;
4026 sal_uInt32 nVal32;
4027 // number of tabulators
4028 rIn.ReadUInt16( nVal16 );
4029 if (!rIn.good() || rIn.remainingSize() / sizeof(nVal32) < nVal16)
4030 return;
4031 for (sal_uInt16 i = 0; i < nVal16; ++i)
4032 rIn.ReadUInt32( nVal32 ); // reading the tabulators
4034 if ( nPMask & 0x200000 )
4035 rIn.ReadUInt16( maParaLevel[ nLevel ].mnBiDi );
4038 nPMask >>= 22;
4039 while( nPMask )
4041 if ( nPMask & 1 )
4043 #ifdef DBG_UTIL
4044 if (!(rManager.rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT))
4046 OSL_FAIL( "PPTParaSheet::Read - unknown attribute, send me this document (SJ)" );
4048 #endif
4049 sal_uInt16 nVal16;
4050 rIn.ReadUInt16( nVal16 );
4052 nPMask >>= 1;
4056 void PPTParaSheet::UpdateBulletRelSize( sal_uInt32 nLevel, sal_uInt16 nFontHeight )
4058 if ( maParaLevel[ nLevel ].mnBulletHeight > 0x7fff ) // a negative value is the absolute bullet height
4060 sal_Int16 nBulletRelSize = static_cast<sal_Int16>(maParaLevel[ nLevel ].mnBulletHeight);
4061 nBulletRelSize = nFontHeight ? ((-nBulletRelSize) * 100 ) / nFontHeight : 100;
4062 if ( nBulletRelSize < 0 ) //bullet size over flow
4063 nBulletRelSize = 100;
4064 maParaLevel[ nLevel ].mnBulletHeight = nBulletRelSize;
4068 PPTStyleSheet::PPTStyleSheet( const DffRecordHeader& rSlideHd, SvStream& rIn, SdrPowerPointImport& rManager,
4069 const PPTTextParagraphStyleAtomInterpreter& rTxPFStyle,
4070 const PPTTextSpecInfo& rTextSpecInfo ) :
4072 PPTNumberFormatCreator ( std::make_unique<PPTExtParaProv>( rManager, rIn, &rSlideHd ) ),
4073 maTxSI ( rTextSpecInfo )
4075 sal_uInt32 nOldFilePos = rIn.Tell();
4077 // default stylesheets
4078 mpCharSheet[ TSS_Type::PageTitle ] = std::make_unique<PPTCharSheet>( TSS_Type::PageTitle );
4079 mpCharSheet[ TSS_Type::Body ] = std::make_unique<PPTCharSheet>( TSS_Type::Body );
4080 mpCharSheet[ TSS_Type::Notes ] = std::make_unique<PPTCharSheet>( TSS_Type::Notes );
4081 mpCharSheet[ TSS_Type::Unused ] = std::make_unique<PPTCharSheet>( TSS_Type::Unused ); // this entry is not used by ppt
4082 mpCharSheet[ TSS_Type::TextInShape ] = std::make_unique<PPTCharSheet>( TSS_Type::TextInShape );
4083 mpParaSheet[ TSS_Type::PageTitle ] = std::make_unique<PPTParaSheet>( TSS_Type::PageTitle );
4084 mpParaSheet[ TSS_Type::Body ] = std::make_unique<PPTParaSheet>( TSS_Type::Body );
4085 mpParaSheet[ TSS_Type::Notes ] = std::make_unique<PPTParaSheet>( TSS_Type::Notes );
4086 mpParaSheet[ TSS_Type::Unused ] = std::make_unique<PPTParaSheet>( TSS_Type::Unused );
4087 mpParaSheet[ TSS_Type::TextInShape ] = std::make_unique<PPTParaSheet>( TSS_Type::TextInShape );
4088 // mpCharSheet[ TSS_Type::QuarterBody ], mpCharSheet[ TSS_Type::HalfBody ], mpCharSheet[ TSS_Type::Title ], mpCharSheet[ TSS_Type::Subtitle ] intentionally null
4089 // mpParaSheet[ TSS_Type::QuarterBody ], mpParaSheet[ TSS_Type::HalfBody ], mpParaSheet[ TSS_Type::Title ], mpParaSheet[ TSS_Type::Subtitle ] intentionally null
4091 /* SJ: try to locate the txMasterStyleAtom in the Environment
4093 it seems that the environment TextStyle is having a higher priority
4094 than the TextStyle that can be found within the master page
4096 bool bFoundTxMasterStyleAtom04 = false;
4097 DffRecordHeader* pEnvHeader = rManager.aDocRecManager.GetRecordHeader( PPT_PST_Environment );
4098 if ( pEnvHeader )
4100 pEnvHeader->SeekToContent( rIn );
4101 DffRecordHeader aTxMasterStyleHd;
4102 auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, pEnvHeader->GetRecEndFilePos());
4103 while (rIn.Tell() < nEndRecPos)
4105 ReadDffRecordHeader( rIn, aTxMasterStyleHd );
4106 if ( aTxMasterStyleHd.nRecType == PPT_PST_TxMasterStyleAtom )
4108 sal_uInt16 nLevelCnt(0);
4109 rIn.ReadUInt16(nLevelCnt);
4111 sal_uInt16 nLev = 0;
4112 bool bFirst = true;
4113 bFoundTxMasterStyleAtom04 = true;
4114 auto nTxEndRecPos = DffPropSet::SanitizeEndPos(rIn, aTxMasterStyleHd.GetRecEndFilePos());
4115 while (rIn.GetError() == ERRCODE_NONE && rIn.Tell() < nTxEndRecPos && nLev < nLevelCnt && nLev < nMaxPPTLevels)
4117 if ( nLev )
4119 mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ nLev ] = mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ nLev - 1 ];
4120 mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev ] = mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev - 1 ];
4122 mpParaSheet[ TSS_Type::TextInShape ]->Read( rManager, rIn, nLev, bFirst );
4123 if ( !nLev )
4125 // set paragraph defaults for instance 4 (TSS_Type::TextInShape)
4126 if ( rTxPFStyle.bValid )
4128 PPTParaLevel& rParaLevel = mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ 0 ];
4129 rParaLevel.mnAsianLineBreak = 0;
4130 if ( rTxPFStyle.bForbiddenRules )
4131 rParaLevel.mnAsianLineBreak |= 1;
4132 if ( !rTxPFStyle.bLatinTextWrap )
4133 rParaLevel.mnAsianLineBreak |= 2;
4134 if ( rTxPFStyle.bHangingPunctuation )
4135 rParaLevel.mnAsianLineBreak |= 4;
4138 mpCharSheet[ TSS_Type::TextInShape ]->Read( rIn, nLev );
4139 mpParaSheet[ TSS_Type::TextInShape ]->UpdateBulletRelSize( nLev, mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev ].mnFontHeight );
4140 bFirst = false;
4141 nLev++;
4143 break;
4145 else
4147 if (!aTxMasterStyleHd.SeekToEndOfRecord(rIn))
4148 break;
4153 rSlideHd.SeekToContent( rIn );
4155 DffRecordHeader aTxMasterStyleHd;
4156 auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, rSlideHd.GetRecEndFilePos());
4157 while (rIn.Tell() < nEndRecPos)
4159 ReadDffRecordHeader( rIn, aTxMasterStyleHd );
4160 if ( aTxMasterStyleHd.nRecType == PPT_PST_TxMasterStyleAtom )
4161 break;
4162 else
4164 if (!aTxMasterStyleHd.SeekToEndOfRecord(rIn))
4165 break;
4168 while ( ( aTxMasterStyleHd.nRecType == PPT_PST_TxMasterStyleAtom ) && ( rIn.Tell() < nEndRecPos ) ) //TODO: aTxMasterStyleHd may be used without having been properly initialized
4170 TSS_Type nInstance = static_cast<TSS_Type>(aTxMasterStyleHd.nRecInstance);
4171 if ( ( nInstance <= TSS_Type::LAST ) &&
4172 ( ( nInstance != TSS_Type::TextInShape ) || !bFoundTxMasterStyleAtom04 ) )
4174 if ( nInstance > TSS_Type::TextInShape )
4176 mpCharSheet[ nInstance ].reset(); // be sure to delete the old one if this instance comes twice
4177 mpParaSheet[ nInstance ].reset();
4179 switch ( nInstance )
4181 case TSS_Type::Subtitle :
4183 mpCharSheet[ TSS_Type::Subtitle ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
4184 mpParaSheet[ TSS_Type::Subtitle ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
4186 break;
4187 case TSS_Type::Title :
4189 mpCharSheet[ TSS_Type::Title ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::PageTitle ] ) );
4190 mpParaSheet[ TSS_Type::Title ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::PageTitle ] ) );
4192 break;
4193 case TSS_Type::HalfBody :
4195 mpCharSheet[ TSS_Type::HalfBody ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
4196 mpParaSheet[ TSS_Type::HalfBody ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
4198 break;
4200 case TSS_Type::QuarterBody :
4202 mpCharSheet[ TSS_Type::QuarterBody ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
4203 mpParaSheet[ TSS_Type::QuarterBody ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
4205 break;
4206 default: break;
4209 sal_uInt16 nLevelCnt(0);
4210 rIn.ReadUInt16(nLevelCnt);
4211 if (nLevelCnt > nMaxPPTLevels)
4213 OSL_FAIL( "PPTStyleSheet::Ppt-TextStylesheet has more than 5 levels! (SJ)" );
4214 nLevelCnt = nMaxPPTLevels;
4216 sal_uInt16 nLev = 0;
4217 bool bFirst = true;
4219 auto nTxEndRecPos = DffPropSet::SanitizeEndPos(rIn, aTxMasterStyleHd.GetRecEndFilePos());
4220 while ( rIn.GetError() == ERRCODE_NONE && rIn.Tell() < nTxEndRecPos && nLev < nLevelCnt )
4222 if ( nLev && ( nInstance < TSS_Type::Subtitle ) )
4224 mpParaSheet[ nInstance ]->maParaLevel[ nLev ] = mpParaSheet[ nInstance ]->maParaLevel[ nLev - 1 ];
4225 mpCharSheet[ nInstance ]->maCharLevel[ nLev ] = mpCharSheet[ nInstance ]->maCharLevel[ nLev - 1 ];
4228 // Exception: Template 5, 6 (MasterTitle Title and SubTitle)
4229 if ( nInstance >= TSS_Type::Subtitle )
4231 bFirst = false;
4233 sal_uInt16 nDontKnow;
4234 rIn.ReadUInt16( nDontKnow );
4236 mpParaSheet[ nInstance ]->Read( rManager, rIn, nLev, bFirst );
4237 mpCharSheet[ nInstance ]->Read( rIn, nLev );
4238 mpParaSheet[ nInstance ]->UpdateBulletRelSize( nLev, mpCharSheet[ nInstance ]->maCharLevel[ nLev ].mnFontHeight );
4239 bFirst = false;
4240 nLev++;
4242 #ifdef DBG_UTIL
4243 if (!(rManager.rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT))
4245 if ( rIn.GetError() == ERRCODE_NONE )
4247 OStringBuffer aMsg;
4248 if ( rIn.Tell() > aTxMasterStyleHd.GetRecEndFilePos() )
4250 aMsg.append("\n reading too many bytes:" +
4251 OString::number(rIn.Tell() - aTxMasterStyleHd.GetRecEndFilePos()));
4253 if ( rIn.Tell() < aTxMasterStyleHd.GetRecEndFilePos() )
4255 aMsg.append("\n reading too few bytes:" +
4256 OString::number(aTxMasterStyleHd.GetRecEndFilePos() - rIn.Tell()));
4258 if (aMsg.getLength())
4260 aMsg.insert(0, "PptStyleSheet::operator>>[]");
4261 OSL_FAIL(aMsg.getStr());
4264 if ( rIn.Tell() != aTxMasterStyleHd.GetRecEndFilePos() )
4265 SAL_WARN( "filter.ms", "SJ: Wrong number of bytes read during import of PPT style");
4267 #endif
4269 if (!aTxMasterStyleHd.SeekToEndOfRecord(rIn))
4270 break;
4271 ReadDffRecordHeader( rIn, aTxMasterStyleHd );
4273 if ( !mpCharSheet[ TSS_Type::Subtitle ] )
4275 mpCharSheet[ TSS_Type::Subtitle ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
4276 mpParaSheet[ TSS_Type::Subtitle ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
4278 if ( !mpCharSheet[ TSS_Type::Title ] )
4280 mpCharSheet[ TSS_Type::Title ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::PageTitle ] ) );
4281 mpParaSheet[ TSS_Type::Title ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::PageTitle ] ) );
4283 if ( !mpCharSheet[ TSS_Type::HalfBody ] )
4285 mpCharSheet[ TSS_Type::HalfBody ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
4286 mpParaSheet[ TSS_Type::HalfBody ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
4288 if ( !mpCharSheet[ TSS_Type::QuarterBody ] )
4290 mpCharSheet[ TSS_Type::QuarterBody ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
4291 mpParaSheet[ TSS_Type::QuarterBody ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
4293 if ( !bFoundTxMasterStyleAtom04 )
4294 { // try to locate the txMasterStyleAtom in the Environment
4295 DffRecordHeader* pEnvHeader2 = rManager.aDocRecManager.GetRecordHeader( PPT_PST_Environment );
4296 if ( pEnvHeader2 )
4298 pEnvHeader2->SeekToContent( rIn );
4299 DffRecordHeader aTxMasterStyleHd2;
4300 auto nEnvEndRecPos = DffPropSet::SanitizeEndPos(rIn, pEnvHeader2->GetRecEndFilePos());
4301 while (rIn.Tell() < nEnvEndRecPos)
4303 ReadDffRecordHeader( rIn, aTxMasterStyleHd2 );
4304 if ( aTxMasterStyleHd2.nRecType == PPT_PST_TxMasterStyleAtom )
4306 sal_uInt16 nLevelCnt;
4307 rIn.ReadUInt16( nLevelCnt );
4309 sal_uInt16 nLev = 0;
4310 bool bFirst = true;
4311 auto nTxEndRecPos = DffPropSet::SanitizeEndPos(rIn, aTxMasterStyleHd2.GetRecEndFilePos());
4312 while ( rIn.GetError() == ERRCODE_NONE && rIn.Tell() < nTxEndRecPos && nLev < nLevelCnt )
4314 if ( nLev )
4316 mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ nLev ] = mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ nLev - 1 ];
4317 mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev ] = mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev - 1 ];
4319 mpParaSheet[ TSS_Type::TextInShape ]->Read( rManager, rIn, nLev, bFirst );
4320 if ( !nLev )
4322 // set paragraph defaults for instance 4 (TSS_Type::TextInShape)
4323 if ( rTxPFStyle.bValid )
4325 PPTParaLevel& rParaLevel = mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ 0 ];
4326 rParaLevel.mnAsianLineBreak = 0;
4327 if ( rTxPFStyle.bForbiddenRules )
4328 rParaLevel.mnAsianLineBreak |= 1;
4329 if ( !rTxPFStyle.bLatinTextWrap )
4330 rParaLevel.mnAsianLineBreak |= 2;
4331 if ( rTxPFStyle.bHangingPunctuation )
4332 rParaLevel.mnAsianLineBreak |= 4;
4335 mpCharSheet[ TSS_Type::TextInShape ]->Read( rIn, nLev );
4336 mpParaSheet[ TSS_Type::TextInShape ]->UpdateBulletRelSize( nLev, mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev ].mnFontHeight );
4337 bFirst = false;
4338 nLev++;
4340 break;
4342 else
4344 if (!aTxMasterStyleHd2.SeekToEndOfRecord(rIn))
4345 break;
4350 rIn.Seek( nOldFilePos );
4352 // will create the default numbulletitem for each instance
4353 for ( auto i : o3tl::enumrange<TSS_Type>() )
4355 sal_uInt16 nLevels, nDepth = 0;
4356 SvxNumRuleType eNumRuleType;
4358 switch ( i )
4360 case TSS_Type::PageTitle :
4361 case TSS_Type::Title :
4362 nLevels = 1;
4363 eNumRuleType = SvxNumRuleType::NUMBERING;
4364 break;
4365 case TSS_Type::Subtitle :
4366 nLevels = SVX_MAX_NUM;
4367 eNumRuleType = SvxNumRuleType::NUMBERING;
4368 break;
4369 case TSS_Type::Body :
4370 case TSS_Type::HalfBody :
4371 case TSS_Type::QuarterBody :
4372 nLevels = SVX_MAX_NUM;
4373 eNumRuleType = SvxNumRuleType::PRESENTATION_NUMBERING;
4374 break;
4375 default :
4376 case TSS_Type::Notes :
4377 case TSS_Type::Unused :
4378 case TSS_Type::TextInShape :
4379 nLevels = SVX_MAX_NUM;
4380 eNumRuleType = SvxNumRuleType::NUMBERING;
4381 break;
4383 SvxNumRule aRule( SvxNumRuleFlags::BULLET_REL_SIZE | SvxNumRuleFlags::BULLET_COLOR,
4384 nLevels, false, eNumRuleType );
4385 for ( sal_uInt16 nCount = 0; nDepth < nLevels; nCount++ )
4387 const PPTParaLevel& rParaLevel = mpParaSheet[ i ]->maParaLevel[ nCount ];
4388 const PPTCharLevel& rCharLevel = mpCharSheet[ i ]->maCharLevel[ nCount ];
4389 SvxNumberFormat aNumberFormat( SVX_NUM_CHAR_SPECIAL );
4390 aNumberFormat.SetBulletChar( ' ' );
4391 GetNumberFormat( rManager, aNumberFormat, nCount, rParaLevel, rCharLevel, i );
4392 aRule.SetLevel( nDepth++, aNumberFormat );
4393 if ( nCount >= 4 )
4395 for ( ;nDepth < nLevels; nDepth++ )
4396 aRule.SetLevel( nDepth, aNumberFormat );
4399 mpNumBulletItem[ i ] = std::make_unique<SvxNumBulletItem>( std::move(aRule), EE_PARA_NUMBULLET );
4403 PPTStyleSheet::~PPTStyleSheet()
4405 for ( auto i : o3tl::enumrange<TSS_Type>() )
4407 mpCharSheet[i].reset();
4408 mpParaSheet[i].reset();
4409 mpNumBulletItem[i].reset();
4413 PPTParaPropSet::PPTParaPropSet()
4414 : mnOriginalTextPos(0)
4415 , mxParaSet( new ImplPPTParaPropSet )
4417 mxParaSet->mnHasAnm = 1;
4420 PPTParaPropSet::PPTParaPropSet( PPTParaPropSet const & rParaPropSet )
4422 mxParaSet = rParaPropSet.mxParaSet;
4423 mnOriginalTextPos = rParaPropSet.mnOriginalTextPos;
4426 PPTParaPropSet::~PPTParaPropSet()
4430 PPTParaPropSet& PPTParaPropSet::operator=( const PPTParaPropSet& rParaPropSet )
4432 if ( this != &rParaPropSet )
4434 mxParaSet = rParaPropSet.mxParaSet;
4435 mnOriginalTextPos = rParaPropSet.mnOriginalTextPos;
4437 return *this;
4440 PPTCharPropSet::PPTCharPropSet(sal_uInt32 nParagraph)
4441 : mnOriginalTextPos(0)
4442 , mnParagraph(nParagraph)
4444 mnHylinkOrigColor = 0;
4445 mbIsHyperlink = false;
4446 mbHardHylinkOrigColor = false;
4447 mnLanguage[ 0 ] = mnLanguage[ 1 ] = mnLanguage[ 2 ] = LANGUAGE_SYSTEM;
4450 PPTCharPropSet::PPTCharPropSet( const PPTCharPropSet& rCharPropSet )
4451 : mpImplPPTCharPropSet( rCharPropSet.mpImplPPTCharPropSet )
4453 mnHylinkOrigColor = rCharPropSet.mnHylinkOrigColor;
4454 mbIsHyperlink = rCharPropSet.mbIsHyperlink;
4455 mbHardHylinkOrigColor = rCharPropSet.mbHardHylinkOrigColor;
4457 mnParagraph = rCharPropSet.mnParagraph;
4458 mnOriginalTextPos = rCharPropSet.mnOriginalTextPos;
4459 maString = rCharPropSet.maString;
4460 mpFieldItem.reset( rCharPropSet.mpFieldItem ? new SvxFieldItem( *rCharPropSet.mpFieldItem ) : nullptr );
4461 mnLanguage[ 0 ] = rCharPropSet.mnLanguage[ 0 ];
4462 mnLanguage[ 1 ] = rCharPropSet.mnLanguage[ 1 ];
4463 mnLanguage[ 2 ] = rCharPropSet.mnLanguage[ 2 ];
4466 PPTCharPropSet::PPTCharPropSet( const PPTCharPropSet& rCharPropSet, sal_uInt32 nParagraph )
4467 : mpImplPPTCharPropSet(rCharPropSet.mpImplPPTCharPropSet)
4469 mnHylinkOrigColor = rCharPropSet.mnHylinkOrigColor;
4470 mbIsHyperlink = rCharPropSet.mbIsHyperlink;
4471 mbHardHylinkOrigColor = rCharPropSet.mbHardHylinkOrigColor;
4473 mnParagraph = nParagraph;
4474 mnOriginalTextPos = rCharPropSet.mnOriginalTextPos;
4475 maString = rCharPropSet.maString;
4476 mpFieldItem.reset( rCharPropSet.mpFieldItem ? new SvxFieldItem( *rCharPropSet.mpFieldItem ) : nullptr );
4477 mnLanguage[ 0 ] = mnLanguage[ 1 ] = mnLanguage[ 2 ] = LANGUAGE_SYSTEM;
4480 PPTCharPropSet::~PPTCharPropSet()
4484 PPTCharPropSet& PPTCharPropSet::operator=( const PPTCharPropSet& rCharPropSet )
4486 if ( this != &rCharPropSet )
4488 mpImplPPTCharPropSet = rCharPropSet.mpImplPPTCharPropSet;
4489 mnOriginalTextPos = rCharPropSet.mnOriginalTextPos;
4490 mnParagraph = rCharPropSet.mnParagraph;
4491 maString = rCharPropSet.maString;
4492 mpFieldItem.reset( rCharPropSet.mpFieldItem ? new SvxFieldItem( *rCharPropSet.mpFieldItem ) : nullptr );
4494 return *this;
4497 void PPTCharPropSet::SetFont( sal_uInt16 nFont )
4499 sal_uInt32 nMask = 1 << PPT_CharAttr_Font;
4500 bool bDoNotMake = (mpImplPPTCharPropSet->mnAttrSet & nMask) != 0;
4502 if ( bDoNotMake )
4503 bDoNotMake = nFont == mpImplPPTCharPropSet->mnFont;
4505 if ( !bDoNotMake )
4507 mpImplPPTCharPropSet->mnFont = nFont;
4508 mpImplPPTCharPropSet->mnAttrSet |= nMask;
4512 void PPTCharPropSet::SetColor( sal_uInt32 nColor )
4514 mpImplPPTCharPropSet->mnColor = nColor;
4515 mpImplPPTCharPropSet->mnAttrSet |= 1 << PPT_CharAttr_FontColor;
4518 PPTRuler::PPTRuler()
4519 : nFlags(0)
4520 , nDefaultTab(0x240)
4521 , nTabCount(0)
4525 PPTRuler::~PPTRuler()
4530 PPTTextRulerInterpreter::PPTTextRulerInterpreter() :
4531 mxImplRuler ( new PPTRuler() )
4535 PPTTextRulerInterpreter::PPTTextRulerInterpreter( PPTTextRulerInterpreter const & rRuler )
4537 mxImplRuler = rRuler.mxImplRuler;
4540 PPTTextRulerInterpreter::PPTTextRulerInterpreter( sal_uInt32 nFileOfs, DffRecordHeader const & rHeader, SvStream& rIn ) :
4541 mxImplRuler ( new PPTRuler() )
4543 if ( nFileOfs == 0xffffffff )
4544 return;
4546 sal_uInt32 nOldPos = rIn.Tell();
4547 DffRecordHeader rHd;
4548 if ( nFileOfs )
4550 rIn.Seek( nFileOfs );
4551 ReadDffRecordHeader( rIn, rHd );
4553 else
4555 rHeader.SeekToContent( rIn );
4556 if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_TextRulerAtom, rHeader.GetRecEndFilePos(), &rHd ) )
4557 nFileOfs++;
4559 if ( nFileOfs )
4561 bool bRecordOk = true;
4563 sal_Int16 nTCount(0);
4564 sal_Int32 i;
4565 rIn.ReadInt32( mxImplRuler->nFlags );
4567 // number of indent levels, unused now
4568 if ( mxImplRuler->nFlags & 2 )
4569 rIn.ReadInt16( nTCount );
4570 if ( mxImplRuler->nFlags & 1 )
4571 rIn.ReadUInt16( mxImplRuler->nDefaultTab );
4572 if ( mxImplRuler->nFlags & 4 )
4574 rIn.ReadInt16(nTCount);
4576 const size_t nMaxPossibleRecords = rIn.remainingSize() / (2*sizeof(sal_uInt16));
4577 const sal_uInt16 nTabCount(nTCount);
4579 bRecordOk = nTabCount <= nMaxPossibleRecords;
4581 if (nTCount && bRecordOk)
4583 mxImplRuler->nTabCount = nTabCount;
4584 mxImplRuler->pTab.reset( new PPTTabEntry[ mxImplRuler->nTabCount ] );
4585 for ( i = 0; i < nTCount; i++ )
4587 rIn.ReadUInt16( mxImplRuler->pTab[ i ].nOffset )
4588 .ReadUInt16( mxImplRuler->pTab[ i ].nStyle );
4593 if (bRecordOk)
4595 for ( i = 0; i < 5; i++ )
4597 if ( mxImplRuler->nFlags & ( 8 << i ) )
4598 rIn.ReadUInt16( mxImplRuler->nTextOfs[ i ] );
4599 if ( mxImplRuler->nFlags & ( 256 << i ) )
4600 rIn.ReadUInt16( mxImplRuler->nBulletOfs[ i ] );
4601 if( mxImplRuler->nBulletOfs[ i ] > 0x7fff)
4603 // workaround
4604 // when bullet offset is > 0x7fff, the paragraph should look like
4605 // * first line text
4606 // second line text
4608 // we add to bullet para indent 0xffff - bullet offset. It looks like
4609 // best we can do for now
4610 mxImplRuler->nTextOfs[ i ] += 0xffff - mxImplRuler->nBulletOfs[ i ];
4611 mxImplRuler->nBulletOfs[ i ] = 0;
4616 rIn.Seek( nOldPos );
4619 bool PPTTextRulerInterpreter::GetDefaultTab( sal_uInt16& nValue ) const
4621 if ( ! ( mxImplRuler->nFlags & 1 ) )
4622 return false;
4623 nValue = mxImplRuler->nDefaultTab;
4624 return true;
4627 bool PPTTextRulerInterpreter::GetTextOfs( sal_uInt32 nLevel, sal_uInt16& nValue ) const
4629 if ( ! ( ( nLevel < 5 ) && ( mxImplRuler->nFlags & ( 8 << nLevel ) ) ) )
4630 return false;
4631 nValue = mxImplRuler->nTextOfs[ nLevel ];
4632 return true;
4635 bool PPTTextRulerInterpreter::GetBulletOfs( sal_uInt32 nLevel, sal_uInt16& nValue ) const
4637 if ( ! ( ( nLevel < 5 ) && ( mxImplRuler->nFlags & ( 256 << nLevel ) ) ) )
4638 return false;
4639 nValue = mxImplRuler->nBulletOfs[ nLevel ];
4640 return true;
4643 PPTTextRulerInterpreter& PPTTextRulerInterpreter::operator=( const PPTTextRulerInterpreter& rRuler )
4645 if ( this != &rRuler )
4647 mxImplRuler = rRuler.mxImplRuler;
4649 return *this;
4652 PPTTextRulerInterpreter::~PPTTextRulerInterpreter()
4656 PPTTextParagraphStyleAtomInterpreter::PPTTextParagraphStyleAtomInterpreter() :
4657 bValid ( false ),
4658 bForbiddenRules ( false ),
4659 bHangingPunctuation ( false ),
4660 bLatinTextWrap ( false )
4664 bool PPTTextParagraphStyleAtomInterpreter::Read( SvStream& rIn, const DffRecordHeader& rRecHd )
4666 bValid = false;
4667 rRecHd.SeekToContent( rIn );
4668 sal_uInt32 nDummy32, nFlags, nRecEndPos = rRecHd.GetRecEndFilePos();
4669 sal_uInt16 nDummy16;
4671 rIn.ReadUInt16( nDummy16 )
4672 .ReadUInt32( nFlags );
4674 if ( nFlags & 0xf && ( rIn.Tell() < nRecEndPos ) )
4675 rIn.ReadUInt16( nDummy16 ); // BuFlags
4676 if ( nFlags & 0x80 && ( rIn.Tell() < nRecEndPos ) )
4677 rIn.ReadUInt16( nDummy16 ); // BuChar
4678 if ( nFlags & 0x10 && ( rIn.Tell() < nRecEndPos ) )
4679 rIn.ReadUInt16( nDummy16 ); // nBuFont;
4680 if ( nFlags & 0x40 && ( rIn.Tell() < nRecEndPos ) )
4681 rIn.ReadUInt16( nDummy16 ); // nBuHeight;
4682 if ( nFlags & 0x0020 && ( rIn.Tell() < nRecEndPos ) )
4683 rIn.ReadUInt32( nDummy32 ); // nBuColor;
4684 if ( nFlags & 0x800 && ( rIn.Tell() < nRecEndPos ) )
4685 rIn.ReadUInt16( nDummy16 ); // AbsJust!
4686 if ( nFlags & 0x400 && ( rIn.Tell() < nRecEndPos ) )
4687 rIn.ReadUInt16( nDummy16 );
4688 if ( nFlags & 0x200 && ( rIn.Tell() < nRecEndPos ) )
4689 rIn.ReadUInt16( nDummy16 );
4690 if ( nFlags & 0x100 && ( rIn.Tell() < nRecEndPos ) )
4691 rIn.ReadUInt16( nDummy16 );
4692 if ( nFlags & 0x1000 && ( rIn.Tell() < nRecEndPos ) )
4693 rIn.ReadUInt16( nDummy16 ); // LineFeed
4694 if ( nFlags & 0x2000 && ( rIn.Tell() < nRecEndPos ) )
4695 rIn.ReadUInt16( nDummy16 ); // nUpperDist
4696 if ( nFlags & 0x4000 && ( rIn.Tell() < nRecEndPos ) )
4697 rIn.ReadUInt16( nDummy16 ); // nLowerDist
4698 if ( nFlags & 0x8000 && ( rIn.Tell() < nRecEndPos ) )
4699 rIn.ReadUInt16( nDummy16 );
4700 if ( nFlags & 0x10000 && ( rIn.Tell() < nRecEndPos ) )
4701 rIn.ReadUInt16( nDummy16 );
4702 if ( nFlags & 0xe0000 && ( rIn.Tell() < nRecEndPos ) )
4704 rIn.ReadUInt16( nDummy16 );
4705 if ( nFlags & 0x20000 )
4706 bForbiddenRules = ( nDummy16 & 1 ) == 1;
4707 if ( nFlags & 0x40000 )
4708 bLatinTextWrap = ( nDummy16 & 2 ) == 0;
4709 if ( nFlags & 0x80000 )
4710 bHangingPunctuation = ( nDummy16 & 4 ) == 4;
4712 nFlags &=~ 0xfffff;
4713 sal_uInt32 nMask = 0x100000;
4714 while ( nFlags && nMask && ( rIn.Tell() < nRecEndPos ) )
4716 if ( nFlags & nMask )
4718 rIn.ReadUInt16( nDummy16 );
4719 nFlags ^= nMask;
4721 nMask <<= 1;
4723 bValid = rIn.Tell() == nRecEndPos;
4724 return bValid;
4727 PPTTextSpecInfo::PPTTextSpecInfo( sal_uInt32 _nCharIdx ) :
4728 nCharIdx ( _nCharIdx ),
4729 nDontKnow ( 1 )
4731 nLanguage[ 0 ] = LANGUAGE_PROCESS_OR_USER_DEFAULT;
4732 nLanguage[ 1 ] = LANGUAGE_SYSTEM;
4733 nLanguage[ 2 ] = LANGUAGE_SYSTEM;
4736 PPTTextSpecInfoAtomInterpreter::PPTTextSpecInfoAtomInterpreter() :
4737 bValid ( false )
4741 bool PPTTextSpecInfoAtomInterpreter::Read( SvStream& rIn, const DffRecordHeader& rRecHd,
4742 sal_uInt16 nRecordType, const PPTTextSpecInfo* pTextSpecDefault )
4744 bValid = false;
4745 sal_uInt32 nCharIdx = 0;
4746 rRecHd.SeekToContent( rIn );
4748 auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, rRecHd.GetRecEndFilePos());
4749 while (rIn.Tell() < nEndRecPos && rIn.good())
4751 if ( nRecordType == PPT_PST_TextSpecInfoAtom )
4753 sal_uInt32 nCharCount(0);
4754 rIn.ReadUInt32( nCharCount );
4755 nCharIdx += nCharCount;
4758 sal_uInt32 nFlags(0);
4759 rIn.ReadUInt32(nFlags);
4761 PPTTextSpecInfo aEntry( nCharIdx );
4762 if ( pTextSpecDefault )
4764 aEntry.nDontKnow = pTextSpecDefault->nDontKnow;
4765 aEntry.nLanguage[ 0 ] = pTextSpecDefault->nLanguage[ 0 ];
4766 aEntry.nLanguage[ 1 ] = pTextSpecDefault->nLanguage[ 1 ];
4767 aEntry.nLanguage[ 2 ] = pTextSpecDefault->nLanguage[ 2 ];
4769 for (sal_uInt32 i = 1; nFlags && i ; i <<= 1)
4771 sal_uInt16 nLang = 0;
4772 switch( nFlags & i )
4774 case 0 : break;
4775 case 1 : rIn.ReadUInt16( aEntry.nDontKnow ); break;
4776 case 2 : rIn.ReadUInt16( nLang ); break;
4777 case 4 : rIn.ReadUInt16( nLang ); break;
4778 default :
4780 rIn.SeekRel( 2 );
4783 if ( nLang )
4785 // #i119985#, we could probably handle this better if we have a
4786 // place to override the final language for weak
4787 // characters/fields to fallback to, rather than the current
4788 // application locale. Assuming that we can determine what the
4789 // default fallback language for a given .ppt, etc is during
4790 // load time.
4791 if (i == 2)
4793 aEntry.nLanguage[ 0 ] = aEntry.nLanguage[ 1 ] = aEntry.nLanguage[ 2 ] = LanguageType(nLang);
4796 nFlags &= ~i;
4798 aList.push_back( aEntry );
4800 bValid = rIn.Tell() == rRecHd.GetRecEndFilePos();
4801 return bValid;
4804 PPTTextSpecInfoAtomInterpreter::~PPTTextSpecInfoAtomInterpreter()
4808 void StyleTextProp9::Read( SvStream& rIn )
4810 rIn.ReadUInt32( mnExtParagraphMask );
4811 if ( mnExtParagraphMask & 0x800000 )
4812 rIn.ReadUInt16( mnBuBlip );
4813 if ( mnExtParagraphMask & 0x2000000 )
4814 rIn.ReadUInt16( mnHasAnm );
4815 if ( mnExtParagraphMask & 0x1000000 )
4816 rIn.ReadUInt32( mnAnmScheme );
4817 if ( mnExtParagraphMask & 0x4000000 )
4818 rIn.ReadUInt32( mpfPP10Ext );
4819 rIn.ReadUInt32( mnExtCharacterMask );
4820 if ( mnExtCharacterMask & 0x100000 )
4821 rIn.ReadUInt32( mncfPP10Ext );
4822 rIn.ReadUInt32( mnSpecialInfoMask );
4823 if ( mnSpecialInfoMask & 0x20 )
4824 rIn.ReadUInt32( mnPP10Ext );
4825 if ( mnSpecialInfoMask & 0x40 )
4826 rIn.ReadUInt16( mfBidi );
4829 PPTStyleTextPropReader::PPTStyleTextPropReader( SvStream& rIn, const DffRecordHeader& rTextHeader,
4830 PPTTextRulerInterpreter const & rRuler, const DffRecordHeader& rExtParaHd, TSS_Type nInstance )
4832 Init(rIn, rTextHeader, rRuler, rExtParaHd, nInstance);
4835 void PPTStyleTextPropReader::ReadParaProps( SvStream& rIn, const DffRecordHeader& rTextHeader,
4836 const OUString& aString, PPTTextRulerInterpreter const & rRuler,
4837 sal_uInt32& nCharCount, bool& bTextPropAtom )
4839 sal_uInt32 nMask = 0; //TODO: nMask initialized here to suppress warning for now, see corresponding TODO below
4840 sal_uInt32 nCharReadCnt = 0;
4841 sal_uInt16 nDummy16;
4843 sal_uInt16 nStringLen = aString.getLength();
4845 DffRecordHeader aTextHd2;
4846 rTextHeader.SeekToContent( rIn );
4847 if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_StyleTextPropAtom, rTextHeader.GetRecEndFilePos(), &aTextHd2 ) )
4848 bTextPropAtom = true;
4849 while ( nCharReadCnt <= nStringLen )
4851 PPTParaPropSet aParaPropSet;
4852 ImplPPTParaPropSet& aSet = *aParaPropSet.mxParaSet;
4853 if ( bTextPropAtom )
4855 rIn.ReadUInt32( nCharCount )
4856 .ReadUInt16( aParaPropSet.mxParaSet->mnDepth ); // indent depth
4858 aParaPropSet.mxParaSet->mnDepth = // taking care of about using not more than 9 outliner levels
4859 std::min(sal_uInt16(8),
4860 aParaPropSet.mxParaSet->mnDepth);
4862 nCharCount--;
4864 rIn.ReadUInt32( nMask );
4865 aSet.mnAttrSet = nMask & 0x207df7;
4866 sal_uInt16 nBulFlg = 0;
4867 if ( nMask & 0xF )
4868 rIn.ReadUInt16( nBulFlg ); // Bullet-HardAttr-Flags
4869 aSet.mpArry[ PPT_ParaAttr_BulletOn ] = ( nBulFlg & 1 ) ? 1 : 0;
4870 aSet.mpArry[ PPT_ParaAttr_BuHardFont ] = ( nBulFlg & 2 ) ? 1 : 0;
4871 aSet.mpArry[ PPT_ParaAttr_BuHardColor ] = ( nBulFlg & 4 ) ? 1 : 0;
4873 // NOTE: one might think that the hard-coded numbers here are the
4874 // same as the PPT_ParaAttr_* constants, but it's NOT always true!
4875 if ( nMask & 0x0080 ) // buChar
4877 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BulletChar ] );
4878 if (!rIn.good())
4880 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BulletChar);
4883 if ( nMask & 0x0010 ) // buTypeface
4885 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BulletFont ] );
4886 if (!rIn.good())
4888 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BulletFont);
4891 if ( nMask & 0x0040 ) // buSize
4893 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BulletHeight ] );
4894 if (!rIn.good()
4895 || !((nMask & (1 << PPT_ParaAttr_BuHardHeight))
4896 && (nBulFlg & (1 << PPT_ParaAttr_BuHardHeight))))
4898 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BulletHeight);
4901 if ( nMask & 0x0020 ) // buColor
4903 sal_uInt32 nVal32;
4904 rIn.ReadUInt32( nVal32 );
4905 if (!rIn.good())
4907 aSet.mnBulletColor = 0; // no flag for this? default it
4909 else
4911 sal_uInt32 nHiByte;
4912 nHiByte = nVal32 >> 24;
4913 if ( nHiByte <= 8 )
4914 nVal32 = nHiByte | PPT_COLSCHEME;
4915 aSet.mnBulletColor = nVal32;
4918 if ( nMask & 0x0800 ) // pfAlignment
4920 rIn.ReadUInt16( nDummy16 );
4921 if (!rIn.good())
4923 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_Adjust);
4925 else
4927 aSet.mpArry[ PPT_ParaAttr_Adjust ] = nDummy16 & 3;
4930 if ( nMask & 0x1000 ) // pfLineSpacing
4932 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_LineFeed ] );
4933 if (!rIn.good())
4935 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_LineFeed);
4938 if ( nMask & 0x2000 ) // pfSpaceBefore
4940 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_UpperDist ] );
4941 if (!rIn.good())
4943 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_UpperDist);
4946 if ( nMask & 0x4000 ) // pfSpaceAfter
4948 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_LowerDist ] );
4949 if (!rIn.good())
4951 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_LowerDist);
4954 if ( nMask & 0x100 ) // pfLeftMargin
4956 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_TextOfs ] );
4957 if (!rIn.good())
4959 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_TextOfs);
4961 else
4963 aSet.mnAttrSet |= 1 << PPT_ParaAttr_TextOfs;
4966 if ( nMask & 0x400 ) // pfIndent
4968 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BulletOfs ] );
4969 if (!rIn.good())
4971 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BulletOfs);
4973 else
4975 aSet.mnAttrSet |= 1 << PPT_ParaAttr_BulletOfs;
4978 if ( nMask & 0x8000 ) // pfDefaultTabSize
4980 rIn.ReadUInt16( nDummy16 );
4981 if (!rIn.good())
4983 // TODO?
4986 if ( nMask & 0x100000 ) // pfTabStops
4988 sal_uInt16 i, nDistance, nAlignment, nNumberOfTabStops = 0;
4989 rIn.ReadUInt16( nNumberOfTabStops );
4990 if (!rIn.good())
4992 // TODO?
4994 else
4996 const size_t nMinRecordSize = 4;
4997 const size_t nMaxRecords = rIn.remainingSize() / nMinRecordSize;
4998 if (nNumberOfTabStops > nMaxRecords)
5000 SAL_WARN("filter.ms", "Parsing error: " << nMaxRecords <<
5001 " max possible entries, but " << nNumberOfTabStops << " claimed, truncating");
5002 nNumberOfTabStops = nMaxRecords;
5004 for (i = 0; i < nNumberOfTabStops; ++i)
5006 rIn.ReadUInt16( nDistance )
5007 .ReadUInt16( nAlignment );
5011 if ( nMask & 0x10000 ) // pfBaseLine
5013 rIn.ReadUInt16( nDummy16 );
5014 if (!rIn.good())
5016 // TODO?
5019 if ( nMask & 0xe0000 ) // pfCharWrap, pfWordWrap, pfOverflow
5021 rIn.ReadUInt16( nDummy16 );
5022 if (!rIn.good())
5023 { // clear flag to avoid invalid access
5024 aSet.mnAttrSet &= ~((1 << PPT_ParaAttr_AsianLB_1)
5025 | (1 << PPT_ParaAttr_AsianLB_2)
5026 | (1 << PPT_ParaAttr_AsianLB_3));
5028 else
5030 if (nMask & 0x20000)
5031 aSet.mpArry[PPT_ParaAttr_AsianLB_1] = nDummy16 & 1;
5032 if (nMask & 0x40000)
5033 aSet.mpArry[PPT_ParaAttr_AsianLB_2] = (nDummy16 >> 1) & 1;
5034 if (nMask & 0x80000)
5035 aSet.mpArry[PPT_ParaAttr_AsianLB_3] = (nDummy16 >> 2) & 1;
5036 aSet.mnAttrSet |= ((nMask >> 17) & 7) << PPT_ParaAttr_AsianLB_1;
5039 if ( nMask & 0x200000 ) // pfTextDirection
5041 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BiDi ] );
5042 if (!rIn.good())
5043 { // clear flag to avoid invalid access
5044 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BiDi);
5048 else
5049 nCharCount = nStringLen;
5051 //if the textofs attr has been read at above, need not to reset.
5052 if ( ( !( aSet.mnAttrSet & 1 << PPT_ParaAttr_TextOfs ) ) && rRuler.GetTextOfs( aParaPropSet.mxParaSet->mnDepth, aSet.mpArry[ PPT_ParaAttr_TextOfs ] ) )
5053 aSet.mnAttrSet |= 1 << PPT_ParaAttr_TextOfs;
5054 if ( ( !( aSet.mnAttrSet & 1 << PPT_ParaAttr_BulletOfs ) ) && rRuler.GetBulletOfs( aParaPropSet.mxParaSet->mnDepth, aSet.mpArry[ PPT_ParaAttr_BulletOfs ] ) )
5055 aSet.mnAttrSet |= 1 << PPT_ParaAttr_BulletOfs;
5056 if ( rRuler.GetDefaultTab( aSet.mpArry[ PPT_ParaAttr_DefaultTab ] ) )
5057 aSet.mnAttrSet |= 1 << PPT_ParaAttr_DefaultTab;
5059 if ( ( nCharCount > nStringLen ) || ( nStringLen < nCharReadCnt + nCharCount ) )
5061 bTextPropAtom = false;
5062 nCharCount = nStringLen - nCharReadCnt;
5063 // please fix the right hand side of
5064 // PPTParaPropSet& PPTParaPropSet::operator=(PPTParaPropSet&),
5065 // it should be a const reference
5066 PPTParaPropSet aTmpPPTParaPropSet;
5067 aParaPropSet = aTmpPPTParaPropSet;
5068 OSL_FAIL( "SJ:PPTStyleTextPropReader::could not get this PPT_PST_StyleTextPropAtom by reading the paragraph attributes" );
5070 PPTParaPropSet* pPara = new PPTParaPropSet( aParaPropSet );
5071 pPara->mnOriginalTextPos = nCharReadCnt;
5072 aParaPropList.emplace_back( pPara );
5073 if ( nCharCount )
5075 sal_uInt32 nCount;
5076 const sal_Unicode* pDat = aString.getStr() + nCharReadCnt;
5077 for ( nCount = 0; nCount < nCharCount; nCount++ )
5079 if ( pDat[ nCount ] == 0xd )
5081 pPara = new PPTParaPropSet( aParaPropSet );
5082 pPara->mnOriginalTextPos = nCharReadCnt + nCount + 1;
5083 aParaPropList.emplace_back( pPara );
5087 nCharReadCnt += nCharCount + 1;
5091 void PPTStyleTextPropReader::ReadCharProps( SvStream& rIn, PPTCharPropSet& aCharPropSet, std::u16string_view aString,
5092 sal_uInt32& nCharCount, sal_uInt32 nCharReadCnt,
5093 bool& bTextPropAtom, sal_uInt32 nExtParaPos,
5094 const std::vector< StyleTextProp9 >& aStyleTextProp9,
5095 sal_uInt32& nExtParaFlags, sal_uInt16& nBuBlip,
5096 sal_uInt16& nHasAnm, sal_uInt32& nAnmScheme )
5098 sal_uInt16 nStringLen = aString.size();
5100 sal_uInt16 nDummy16;
5101 rIn.ReadUInt16( nDummy16 );
5102 nCharCount = (rIn.good()) ? nDummy16 : 0;
5103 rIn.ReadUInt16( nDummy16 );
5105 sal_Int32 nCharsToRead = nStringLen - ( nCharReadCnt + nCharCount );
5106 if ( nCharsToRead < 0 )
5108 nCharCount = nStringLen - nCharReadCnt;
5109 if ( nCharsToRead < -1 )
5111 bTextPropAtom = false;
5112 OSL_FAIL( "SJ:PPTStyleTextPropReader::could not get this PPT_PST_StyleTextPropAtom by reading the character attributes" );
5115 ImplPPTCharPropSet& aSet = *aCharPropSet.mpImplPPTCharPropSet;
5117 // character attributes
5118 sal_uInt32 nMask(0);
5119 rIn.ReadUInt32( nMask );
5120 if ( static_cast<sal_uInt16>(nMask) )
5122 aSet.mnAttrSet |= static_cast<sal_uInt16>(nMask);
5123 rIn.ReadUInt16( aSet.mnFlags );
5125 if ( nMask & 0x10000 ) // cfTypeface
5127 rIn.ReadUInt16( aSet.mnFont );
5128 aSet.mnAttrSet |= 1 << PPT_CharAttr_Font;
5130 if ( nMask & 0x200000 ) // cfFEOldTypeface
5132 rIn.ReadUInt16( aSet.mnAsianOrComplexFont );
5133 aSet.mnAttrSet |= 1 << PPT_CharAttr_AsianOrComplexFont;
5135 if ( nMask & 0x400000 ) // cfANSITypeface
5137 rIn.ReadUInt16( aSet.mnANSITypeface );
5138 aSet.mnAttrSet |= 1 << PPT_CharAttr_ANSITypeface;
5140 if ( nMask & 0x800000 ) // cfSymbolTypeface
5142 rIn.ReadUInt16( aSet.mnSymbolFont );
5143 aSet.mnAttrSet |= 1 << PPT_CharAttr_Symbol;
5145 if ( nMask & 0x20000 ) // cfSize
5147 rIn.ReadUInt16( aSet.mnFontHeight );
5148 aSet.mnAttrSet |= 1 << PPT_CharAttr_FontHeight;
5150 if ( nMask & 0x40000 ) // cfColor
5152 sal_uInt32 nVal(0);
5153 rIn.ReadUInt32( nVal );
5154 if ( !( nVal & 0xff000000 ) )
5155 nVal = PPT_COLSCHEME_HINTERGRUND;
5156 aSet.mnColor = nVal;
5157 aSet.mnAttrSet |= 1 << PPT_CharAttr_FontColor;
5159 if ( nMask & 0x80000 ) // cfPosition
5161 rIn.ReadUInt16( aSet.mnEscapement );
5162 aSet.mnAttrSet |= 1 << PPT_CharAttr_Escapement;
5164 if ( !nExtParaPos )
5165 return;
5167 sal_uInt32 nExtBuInd = nMask & 0x3c00;
5168 if ( nExtBuInd )
5169 nExtBuInd = ( aSet.mnFlags & 0x3c00 ) >> 10;
5170 if ( nExtBuInd < aStyleTextProp9.size() )
5172 nExtParaFlags = aStyleTextProp9[ nExtBuInd ].mnExtParagraphMask;
5173 nBuBlip = aStyleTextProp9[ nExtBuInd ].mnBuBlip;
5174 nHasAnm = aStyleTextProp9[ nExtBuInd ].mnHasAnm;
5175 nAnmScheme = aStyleTextProp9[ nExtBuInd ].mnAnmScheme;
5179 void PPTStyleTextPropReader::Init( SvStream& rIn, const DffRecordHeader& rTextHeader,
5180 PPTTextRulerInterpreter const & rRuler, const DffRecordHeader& rExtParaHd, TSS_Type nInstance )
5182 sal_uInt32 nOldPos = rIn.Tell();
5183 sal_uInt32 nExtParaPos = ( rExtParaHd.nRecType == PPT_PST_ExtendedParagraphAtom ) ? rExtParaHd.nFilePos + 8 : 0;
5185 std::vector< StyleTextProp9 > aStyleTextProp9;
5186 if ( rExtParaHd.nRecType == PPT_PST_ExtendedParagraphAtom )
5188 rIn.Seek( rExtParaHd.nFilePos + 8 );
5190 auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, rExtParaHd.GetRecEndFilePos());
5191 while( ( rIn.GetError() == ERRCODE_NONE ) && ( rIn.Tell() < nEndRecPos ) )
5193 aStyleTextProp9.emplace_back();
5194 aStyleTextProp9.back().Read( rIn );
5196 rIn.Seek( nOldPos );
5199 OUString aString;
5200 DffRecordHeader aTextHd;
5201 ReadDffRecordHeader( rIn, aTextHd );
5202 sal_uInt32 nMaxLen = aTextHd.nRecLen;
5203 if ( nMaxLen >= 0xFFFF )
5204 nMaxLen = 0xFFFE;
5206 if( aTextHd.nRecType == PPT_PST_TextCharsAtom )
5208 std::vector<sal_Unicode> aBuf(( nMaxLen >> 1 ) + 1);
5209 void* pDest = aBuf.data();
5210 auto nRead = rIn.ReadBytes(pDest, nMaxLen);
5211 if (nRead != nMaxLen)
5212 memset(static_cast<char*>(pDest) + nRead, 0, nMaxLen - nRead);
5213 nMaxLen >>= 1;
5214 aBuf[nMaxLen] = 0;
5216 sal_uInt32 i;
5217 sal_Unicode* pPtr = aBuf.data();
5219 #ifdef OSL_BIGENDIAN
5220 sal_Unicode nTemp;
5221 for ( i = 0; i < nMaxLen; i++ )
5223 nTemp = *pPtr;
5224 *pPtr++ = ( nTemp << 8 ) | ( nTemp >> 8 );
5226 pPtr = aBuf.data();
5227 #endif
5229 for ( i = 0; i < nMaxLen; pPtr++, i++ )
5231 sal_Unicode nChar = *pPtr;
5232 if ( !nChar )
5233 break;
5234 if ( ( nChar & 0xff00 ) == 0xf000 ) // in this special case we got a symbol
5235 aSpecMarkerList.push_back( static_cast<sal_uInt32>( i | PPT_SPEC_SYMBOL ) );
5236 else if ( nChar == 0xd )
5238 if ( nInstance == TSS_Type::PageTitle )
5239 *pPtr = 0xb;
5240 else
5241 aSpecMarkerList.push_back( static_cast<sal_uInt32>( i | PPT_SPEC_NEWLINE ) );
5244 if ( i )
5245 aString = OUString(aBuf.data(), i);
5247 else if( aTextHd.nRecType == PPT_PST_TextBytesAtom )
5249 std::unique_ptr<char[]> pBuf(new char[ nMaxLen + 1 ]);
5250 nMaxLen = rIn.ReadBytes(pBuf.get(), nMaxLen);
5251 pBuf[ nMaxLen ] = 0;
5252 char* pPtr = pBuf.get();
5253 for (;;)
5255 char cLo = *pPtr;
5256 if ( cLo == 0 )
5257 break;
5258 if ( cLo == 0xd )
5260 if ( nInstance == TSS_Type::PageTitle )
5261 *pPtr = 0xb;
5262 else
5263 aSpecMarkerList.push_back( static_cast<sal_uInt32>( (pPtr - pBuf.get()) | PPT_SPEC_NEWLINE ) );
5265 pPtr++;
5267 sal_Int32 nLen = pPtr - pBuf.get();
5268 if ( nLen )
5269 aString = OUString( pBuf.get(), nLen, RTL_TEXTENCODING_MS_1252 );
5271 else
5273 // no chars, but potentially char/para props?
5274 sal_uInt32 nCharCount;
5275 bool bTextPropAtom = false;
5276 ReadParaProps( rIn, rTextHeader, aString, rRuler, nCharCount, bTextPropAtom );
5278 if ( bTextPropAtom )
5280 // yeah, StyleTextProp is there, read it all & push to
5281 // aParaPropList
5282 PPTCharPropSet aCharPropSet(0);
5283 aCharPropSet.mnOriginalTextPos = 0;
5285 sal_uInt32 nExtParaFlags = 0, nAnmScheme = 0;
5286 sal_uInt16 nBuBlip = 0xffff, nHasAnm = 0;
5287 ReadCharProps( rIn, aCharPropSet, aString, nCharCount, 0/*nCharReadCnt*/,
5288 bTextPropAtom, nExtParaPos, aStyleTextProp9, nExtParaFlags,
5289 nBuBlip, nHasAnm, nAnmScheme );
5291 aCharPropList.push_back(std::make_unique<PPTCharPropSet>(aCharPropSet, 0));
5295 if ( !aString.isEmpty() )
5297 sal_uInt32 nCharCount;
5298 bool bTextPropAtom = false;
5300 ReadParaProps( rIn, rTextHeader, aString, rRuler, nCharCount, bTextPropAtom );
5302 bool bEmptyParaPossible = true;
5303 sal_uInt32 nCharReadCnt = 0;
5304 sal_uInt32 nCurrentPara = 0;
5305 size_t i = 1; // points to the next element to process
5306 sal_uInt32 nCurrentSpecMarker = aSpecMarkerList.empty() ? 0 : aSpecMarkerList[0];
5307 sal_uInt32 nStringLen = aString.getLength();
5309 while ( nCharReadCnt < nStringLen )
5311 sal_uInt32 nExtParaFlags = 0, nLatestParaUpdate = 0xffffffff, nAnmScheme = 0;
5312 sal_uInt16 nBuBlip = 0xffff, nHasAnm = 0;
5314 PPTCharPropSet aCharPropSet( nCurrentPara );
5315 if ( bTextPropAtom )
5317 ReadCharProps( rIn, aCharPropSet, aString, nCharCount, nCharReadCnt,
5318 bTextPropAtom, nExtParaPos, aStyleTextProp9, nExtParaFlags,
5319 nBuBlip, nHasAnm, nAnmScheme );
5320 if (!rIn.good())
5321 break;
5323 else
5324 nCharCount = nStringLen;
5326 sal_uInt32 nLen;
5327 while( nCharCount )
5329 if ( nExtParaPos && ( nLatestParaUpdate != nCurrentPara ) && ( nCurrentPara < aParaPropList.size() ) )
5331 PPTParaPropSet* pPropSet = aParaPropList[ nCurrentPara ].get();
5332 pPropSet->mxParaSet->mnExtParagraphMask = nExtParaFlags;
5333 if ( nExtParaFlags & 0x800000 )
5334 pPropSet->mxParaSet->mnBuBlip = nBuBlip;
5335 if ( nExtParaFlags & 0x01000000 )
5336 pPropSet->mxParaSet->mnAnmScheme = nAnmScheme;
5337 if ( nExtParaFlags & 0x02000000 )
5338 pPropSet->mxParaSet->mnHasAnm = nHasAnm;
5339 nLatestParaUpdate = nCurrentPara;
5341 aCharPropSet.mnOriginalTextPos = nCharReadCnt;
5342 if ( nCurrentSpecMarker && ( ( nCurrentSpecMarker & 0xffff ) < ( nCharReadCnt + nCharCount ) ) )
5344 if ( nCurrentSpecMarker & PPT_SPEC_NEWLINE )
5346 nLen = ( nCurrentSpecMarker & 0xffff ) - nCharReadCnt;
5347 if ( nLen )
5348 aCharPropSet.maString = aString.copy( nCharReadCnt, nLen );
5349 else if ( bEmptyParaPossible )
5350 aCharPropSet.maString.clear();
5351 if ( nLen || bEmptyParaPossible )
5352 aCharPropList.push_back(
5353 std::make_unique<PPTCharPropSet>(aCharPropSet, nCurrentPara));
5354 nCurrentPara++;
5355 nLen++;
5356 nCharReadCnt += nLen;
5357 nCharCount -= nLen;
5358 bEmptyParaPossible = true;
5360 else if ( nCurrentSpecMarker & PPT_SPEC_SYMBOL )
5362 if ( ( nCurrentSpecMarker & 0xffff ) != nCharReadCnt )
5364 nLen = ( nCurrentSpecMarker & 0xffff ) - nCharReadCnt;
5365 aCharPropSet.maString = aString.copy(nCharReadCnt, nLen);
5366 aCharPropList.push_back(
5367 std::make_unique<PPTCharPropSet>(aCharPropSet, nCurrentPara));
5368 nCharCount -= nLen;
5369 nCharReadCnt += nLen;
5371 PPTCharPropSet* pCPropSet = new PPTCharPropSet( aCharPropSet, nCurrentPara );
5372 pCPropSet->maString = aString.copy(nCharReadCnt, 1);
5373 if ( aCharPropSet.mpImplPPTCharPropSet->mnAttrSet & ( 1 << PPT_CharAttr_Symbol ) )
5374 pCPropSet->SetFont( aCharPropSet.mpImplPPTCharPropSet->mnSymbolFont );
5375 aCharPropList.emplace_back( pCPropSet );
5376 nCharCount--;
5377 nCharReadCnt++;
5378 bEmptyParaPossible = false;
5380 nCurrentSpecMarker = ( i < aSpecMarkerList.size() ) ? aSpecMarkerList[ i++ ] : 0;
5382 else
5384 if (nCharReadCnt > o3tl::make_unsigned(aString.getLength()))
5385 aCharPropSet.maString = OUString();
5386 else
5388 sal_Int32 nStrLen = nCharCount;
5389 sal_Int32 nMaxStrLen = aString.getLength() - nCharReadCnt;
5390 if (nStrLen > nMaxStrLen)
5391 nStrLen = nMaxStrLen;
5392 aCharPropSet.maString = aString.copy(nCharReadCnt, nStrLen);
5394 aCharPropList.push_back(
5395 std::make_unique<PPTCharPropSet>(aCharPropSet, nCurrentPara));
5396 nCharReadCnt += nCharCount;
5397 bEmptyParaPossible = false;
5398 break;
5402 if ( !aCharPropList.empty() && ( aCharPropList.back()->mnParagraph != nCurrentPara ) )
5404 PPTCharPropSet* pCharPropSet = new PPTCharPropSet( *aCharPropList.back(), nCurrentPara );
5405 pCharPropSet->maString.clear();
5406 pCharPropSet->mnOriginalTextPos = nStringLen - 1;
5407 aCharPropList.emplace_back( pCharPropSet );
5410 rIn.Seek( nOldPos );
5413 PPTStyleTextPropReader::~PPTStyleTextPropReader()
5417 PPTPortionObj::PPTPortionObj( const PPTStyleSheet& rStyleSheet, TSS_Type nInstance, sal_uInt32 nDepth ) :
5418 PPTCharPropSet ( 0 ),
5419 mrStyleSheet ( rStyleSheet ),
5420 mnInstance ( nInstance ),
5421 mnDepth ( std::min<sal_uInt32>( nDepth, 4 ) )
5425 PPTPortionObj::PPTPortionObj( const PPTCharPropSet& rCharPropSet, const PPTStyleSheet& rStyleSheet, TSS_Type nInstance, sal_uInt32 nDepth ) :
5426 PPTCharPropSet ( rCharPropSet ),
5427 mrStyleSheet ( rStyleSheet ),
5428 mnInstance ( nInstance ),
5429 mnDepth ( std::min<sal_uInt32>( nDepth, 4 ) )
5433 PPTPortionObj::PPTPortionObj( const PPTPortionObj& rPortionObj ) :
5434 PPTCharPropSet ( rPortionObj ),
5435 mrStyleSheet ( rPortionObj.mrStyleSheet ),
5436 mnInstance ( rPortionObj.mnInstance ),
5437 mnDepth ( rPortionObj.mnDepth )
5441 PPTPortionObj::~PPTPortionObj()
5445 bool PPTPortionObj::GetAttrib( sal_uInt32 nAttr, sal_uInt32& rRetValue, TSS_Type nDestinationInstance ) const
5447 sal_uInt32 nMask = 1 << nAttr;
5448 rRetValue = 0;
5450 bool bIsHardAttribute = ( ( mpImplPPTCharPropSet->mnAttrSet & nMask ) != 0 );
5452 if ( bIsHardAttribute )
5454 switch ( nAttr )
5456 case PPT_CharAttr_Bold :
5457 case PPT_CharAttr_Italic :
5458 case PPT_CharAttr_Underline :
5459 case PPT_CharAttr_Shadow :
5460 case PPT_CharAttr_Strikeout :
5461 case PPT_CharAttr_Embossed :
5462 rRetValue = ( mpImplPPTCharPropSet->mnFlags & nMask ) ? 1 : 0;
5463 break;
5464 case PPT_CharAttr_Font :
5465 rRetValue = mpImplPPTCharPropSet->mnFont;
5466 break;
5467 case PPT_CharAttr_AsianOrComplexFont :
5468 rRetValue = mpImplPPTCharPropSet->mnAsianOrComplexFont;
5469 break;
5470 case PPT_CharAttr_FontHeight :
5471 rRetValue = mpImplPPTCharPropSet->mnFontHeight;
5472 break;
5473 case PPT_CharAttr_FontColor :
5474 rRetValue = mpImplPPTCharPropSet->mnColor;
5475 break;
5476 case PPT_CharAttr_Escapement :
5477 rRetValue = mpImplPPTCharPropSet->mnEscapement;
5478 break;
5479 default :
5480 OSL_FAIL( "SJ:PPTPortionObj::GetAttrib ( hard attribute does not exist )" );
5483 else
5485 const PPTCharLevel& rCharLevel = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ mnDepth ];
5486 PPTCharLevel* pCharLevel = nullptr;
5487 if ( ( nDestinationInstance == TSS_Type::Unknown )
5488 || ( mnDepth && ( ( mnInstance == TSS_Type::Subtitle ) || ( mnInstance == TSS_Type::TextInShape ) ) ) )
5489 bIsHardAttribute = true;
5490 else if ( nDestinationInstance != mnInstance )
5491 pCharLevel = &mrStyleSheet.mpCharSheet[ nDestinationInstance ]->maCharLevel[ mnDepth ];
5492 switch( nAttr )
5494 case PPT_CharAttr_Bold :
5495 case PPT_CharAttr_Italic :
5496 case PPT_CharAttr_Underline :
5497 case PPT_CharAttr_Shadow :
5498 case PPT_CharAttr_Strikeout :
5499 case PPT_CharAttr_Embossed :
5501 rRetValue = ( rCharLevel.mnFlags & nMask ) ? 1 : 0;
5502 if ( pCharLevel )
5504 sal_uInt32 nTmp = ( pCharLevel->mnFlags & nMask ) ? 1 : 0;
5505 if ( rRetValue != nTmp )
5506 bIsHardAttribute = true;
5509 break;
5510 case PPT_CharAttr_Font :
5512 rRetValue = rCharLevel.mnFont;
5513 if ( pCharLevel && ( rRetValue != pCharLevel->mnFont ) )
5514 bIsHardAttribute = true;
5516 break;
5517 case PPT_CharAttr_AsianOrComplexFont :
5519 rRetValue = rCharLevel.mnAsianOrComplexFont;
5520 if ( pCharLevel && ( rRetValue != pCharLevel->mnAsianOrComplexFont ) )
5521 bIsHardAttribute = true;
5523 break;
5524 case PPT_CharAttr_FontHeight :
5526 rRetValue = rCharLevel.mnFontHeight;
5527 if ( pCharLevel && ( rRetValue != pCharLevel->mnFontHeight ) )
5528 bIsHardAttribute = true;
5530 break;
5531 case PPT_CharAttr_FontColor :
5533 rRetValue = rCharLevel.mnFontColor;
5534 if ( pCharLevel && ( rRetValue != pCharLevel->mnFontColor ) )
5535 bIsHardAttribute = true;
5537 break;
5538 case PPT_CharAttr_Escapement :
5540 rRetValue = rCharLevel.mnEscapement;
5541 if ( pCharLevel && ( rRetValue != pCharLevel->mnEscapement ) )
5542 bIsHardAttribute = true;
5544 break;
5545 default :
5546 OSL_FAIL( "SJ:PPTPortionObj::GetAttrib ( attribute does not exist )" );
5549 return bIsHardAttribute;
5552 void PPTPortionObj::ApplyTo( SfxItemSet& rSet, SdrPowerPointImport& rManager, TSS_Type nDestinationInstance )
5554 ApplyTo( rSet, rManager, nDestinationInstance, nullptr );
5557 void PPTPortionObj::ApplyTo( SfxItemSet& rSet, SdrPowerPointImport& rManager, TSS_Type nDestinationInstance, const PPTTextObj* pTextObj )
5559 sal_uInt32 nVal;
5560 if ( GetAttrib( PPT_CharAttr_Bold, nVal, nDestinationInstance ) )
5562 rSet.Put( SvxWeightItem( nVal != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT ) );
5563 rSet.Put( SvxWeightItem( nVal != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT_CJK ) );
5564 rSet.Put( SvxWeightItem( nVal != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT_CTL ) );
5566 if ( GetAttrib( PPT_CharAttr_Italic, nVal, nDestinationInstance ) )
5568 rSet.Put( SvxPostureItem( nVal != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) );
5569 rSet.Put( SvxPostureItem( nVal != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC_CJK ) );
5570 rSet.Put( SvxPostureItem( nVal != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC_CTL ) );
5572 if ( GetAttrib( PPT_CharAttr_Underline, nVal, nDestinationInstance ) )
5573 rSet.Put( SvxUnderlineItem( nVal != 0 ? LINESTYLE_SINGLE : LINESTYLE_NONE, EE_CHAR_UNDERLINE ) );
5575 if ( GetAttrib( PPT_CharAttr_Shadow, nVal, nDestinationInstance ) )
5576 rSet.Put( SvxShadowedItem( nVal != 0, EE_CHAR_SHADOW ) );
5578 if ( GetAttrib( PPT_CharAttr_Strikeout, nVal, nDestinationInstance ) )
5579 rSet.Put( SvxCrossedOutItem( nVal != 0 ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ) );
5581 sal_uInt32 nAsianFontId = 0xffff;
5582 if ( GetAttrib( PPT_CharAttr_AsianOrComplexFont, nAsianFontId, nDestinationInstance ) )
5584 if ( nAsianFontId != 0xffff )
5586 const PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nAsianFontId );
5587 if ( pFontEnityAtom )
5589 rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName,
5590 OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO_CJK ) );
5591 rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName,
5592 OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO_CTL ) );
5596 if ( GetAttrib( PPT_CharAttr_Font, nVal, nDestinationInstance ) )
5598 const PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nVal );
5599 if ( pFontEnityAtom )
5601 rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName, OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO ) );
5603 // #i119475# bullet font info for CJK and CTL
5604 if ( RTL_TEXTENCODING_SYMBOL == pFontEnityAtom->eCharSet )
5606 rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName, OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO_CJK ) );
5607 rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName, OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO_CTL ) );
5611 if ( GetAttrib( PPT_CharAttr_FontHeight, nVal, nDestinationInstance ) ) // Schriftgrad in Point
5613 sal_uInt32 nHeight = rManager.ScalePoint( nVal );
5614 rSet.Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
5615 rSet.Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
5616 rSet.Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
5619 if ( GetAttrib( PPT_CharAttr_Embossed, nVal, nDestinationInstance ) )
5620 rSet.Put( SvxCharReliefItem( nVal != 0 ? FontRelief::Embossed : FontRelief::NONE, EE_CHAR_RELIEF ) );
5621 if ( nVal ) /* if Embossed is set, the font color depends to the fillstyle/color of the object,
5622 if the object has no fillstyle, the font color depends to fillstyle of the background */
5624 Color aDefColor( COL_BLACK );
5625 sal_uInt32 eFillType = mso_fillSolid;
5626 if ( rManager.GetPropertyValue( DFF_Prop_fNoFillHitTest, 0 ) & 0x10 )
5627 eFillType = rManager.GetPropertyValue(DFF_Prop_fillType, mso_fillSolid);
5628 else
5629 eFillType = mso_fillBackground;
5630 switch( eFillType )
5632 case mso_fillShade :
5633 case mso_fillShadeCenter :
5634 case mso_fillShadeShape :
5635 case mso_fillShadeScale :
5636 case mso_fillShadeTitle :
5637 case mso_fillSolid :
5638 aDefColor = rManager.MSO_CLR_ToColor( rManager.GetPropertyValue( DFF_Prop_fillColor, 0 ) );
5639 break;
5640 case mso_fillPattern :
5641 aDefColor = rManager.MSO_CLR_ToColor( rManager.GetPropertyValue( DFF_Prop_fillBackColor, 0 ) );
5642 break;
5643 case mso_fillTexture :
5645 Graphic aGraf;
5646 if ( rManager.GetBLIP( rManager.GetPropertyValue( DFF_Prop_fillBlip, 0 ), aGraf ) )
5648 Bitmap aBmp( aGraf.GetBitmapEx().GetBitmap() );
5649 Size aSize( aBmp.GetSizePixel() );
5650 if ( aSize.Width() && aSize.Height() )
5652 if ( aSize.Width () > 64 )
5653 aSize.setWidth( 64 );
5654 if ( aSize.Height() > 64 )
5655 aSize.setHeight( 64 );
5657 Bitmap::ScopedReadAccess pAcc(aBmp);
5658 if( pAcc )
5660 sal_uLong nRt = 0, nGn = 0, nBl = 0;
5661 const tools::Long nWidth = aSize.Width();
5662 const tools::Long nHeight = aSize.Height();
5664 if( pAcc->HasPalette() )
5666 for( tools::Long nY = 0; nY < nHeight; nY++ )
5668 Scanline pScanline = pAcc->GetScanline( nY );
5669 for( tools::Long nX = 0; nX < nWidth; nX++ )
5671 const BitmapColor& rCol = pAcc->GetPaletteColor( pAcc->GetIndexFromData( pScanline, nX ) );
5672 nRt+=rCol.GetRed(); nGn+=rCol.GetGreen(); nBl+=rCol.GetBlue();
5676 else
5678 for( tools::Long nY = 0; nY < nHeight; nY++ )
5680 Scanline pScanline = pAcc->GetScanline( nY );
5681 for( tools::Long nX = 0; nX < nWidth; nX++ )
5683 const BitmapColor aCol( pAcc->GetPixelFromData( pScanline, nX ) );
5684 nRt+=aCol.GetRed(); nGn+=aCol.GetGreen(); nBl+=aCol.GetBlue();
5688 pAcc.reset();
5689 sal_uInt32 nC = aSize.Width() * aSize.Height();
5690 nRt /= nC;
5691 nGn /= nC;
5692 nBl /= nC;
5693 aDefColor = Color(sal_uInt8( nRt ), sal_uInt8( nGn ),sal_uInt8( nBl ) );
5698 break;
5699 case mso_fillBackground :
5701 if ( pTextObj ) // the textobject is needed
5703 const SfxItemSet* pItemSet = pTextObj->GetBackground();
5704 if ( pItemSet )
5706 const XFillStyleItem* pFillStyleItem = pItemSet->GetItemIfSet( XATTR_FILLSTYLE, false );
5707 if ( pFillStyleItem )
5709 drawing::FillStyle eFillStyle = pFillStyleItem->GetValue();
5710 switch( eFillStyle )
5712 case drawing::FillStyle_SOLID :
5714 const XColorItem* pFillColorItem = pItemSet->GetItemIfSet( XATTR_FILLCOLOR, false );
5715 if ( pFillColorItem )
5716 aDefColor = pFillColorItem->GetColorValue();
5718 break;
5719 case drawing::FillStyle_GRADIENT :
5721 const XFillGradientItem* pGradientItem = pItemSet->GetItemIfSet( XATTR_FILLGRADIENT, false );
5722 if ( pGradientItem )
5723 aDefColor = Color(pGradientItem->GetGradientValue().GetColorStops().front().getStopColor());
5725 break;
5726 case drawing::FillStyle_HATCH :
5727 case drawing::FillStyle_BITMAP :
5728 aDefColor = COL_WHITE;
5729 break;
5730 default: break;
5736 break;
5737 default: break;
5739 rSet.Put( SvxColorItem( aDefColor, EE_CHAR_COLOR ) );
5741 else
5743 if ( GetAttrib( PPT_CharAttr_FontColor, nVal, nDestinationInstance ) ) // text color (4Byte-Arg)
5745 Color aCol( rManager.MSO_TEXT_CLR_ToColor( nVal ) );
5746 rSet.Put( SvxColorItem( aCol, EE_CHAR_COLOR ) );
5747 if ( nDestinationInstance == TSS_Type::Unknown )
5748 mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ mnDepth ].mnFontColorInStyleSheet = aCol;
5750 else if ( nVal & 0x0f000000 ) // this is not a hard attribute, but maybe the page has a different colorscheme,
5751 { // so that in this case we must use a hard color attribute
5752 Color aCol( rManager.MSO_TEXT_CLR_ToColor( nVal ) );
5753 Color& aColorInSheet = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ mnDepth ].mnFontColorInStyleSheet;
5754 if ( aColorInSheet != aCol )
5755 rSet.Put( SvxColorItem( aCol, EE_CHAR_COLOR ) );
5759 if ( GetAttrib( PPT_CharAttr_Escapement, nVal, nDestinationInstance ) ) // super-/subscript in %
5761 sal_uInt16 nEsc = 0;
5762 sal_uInt8 nProp = 100;
5764 if ( nVal )
5766 nEsc = static_cast<sal_Int16>(nVal);
5767 nProp = DFLT_ESC_PROP;
5769 SvxEscapementItem aItem( nEsc, nProp, EE_CHAR_ESCAPEMENT );
5770 rSet.Put( aItem );
5772 if ( mnLanguage[ 0 ] )
5773 rSet.Put( SvxLanguageItem( mnLanguage[ 0 ], EE_CHAR_LANGUAGE ) );
5774 if ( mnLanguage[ 1 ] )
5775 rSet.Put( SvxLanguageItem( mnLanguage[ 1 ], EE_CHAR_LANGUAGE_CJK ) );
5776 if ( mnLanguage[ 2 ] )
5777 rSet.Put( SvxLanguageItem( mnLanguage[ 2 ], EE_CHAR_LANGUAGE_CTL ) );
5780 SvxFieldItem* PPTPortionObj::GetTextField()
5782 if ( mpFieldItem )
5783 return new SvxFieldItem( *mpFieldItem );
5784 return nullptr;
5787 namespace
5789 sal_uInt16 sanitizeForMaxPPTLevels(sal_uInt16 nDepth)
5791 if (nDepth >= nMaxPPTLevels)
5793 SAL_WARN("filter.ms", "Para Style Sheet depth " << nDepth << " but " << nMaxPPTLevels - 1 << " is max possible");
5794 nDepth = nMaxPPTLevels - 1;
5796 return nDepth;
5800 PPTParagraphObj::PPTParagraphObj( const PPTStyleSheet& rStyleSheet, TSS_Type nInstance, sal_uInt16 nDepth ) :
5801 PPTNumberFormatCreator ( nullptr ),
5802 mrStyleSheet ( rStyleSheet ),
5803 mnInstance ( nInstance ),
5804 mnCurrentObject ( 0 )
5806 mxParaSet->mnDepth = sanitizeForMaxPPTLevels(nDepth);
5809 PPTParagraphObj::PPTParagraphObj( PPTStyleTextPropReader& rPropReader,
5810 size_t const nCurParaPos, size_t& rnCurCharPos,
5811 const PPTStyleSheet& rStyleSheet,
5812 TSS_Type nInstance, PPTTextRulerInterpreter const & rRuler ) :
5813 PPTParaPropSet ( *rPropReader.aParaPropList[nCurParaPos] ),
5814 PPTNumberFormatCreator ( nullptr ),
5815 PPTTextRulerInterpreter ( rRuler ),
5816 mrStyleSheet ( rStyleSheet ),
5817 mnInstance ( nInstance ),
5818 mnCurrentObject ( 0 )
5820 if (rnCurCharPos >= rPropReader.aCharPropList.size())
5821 return;
5823 sal_uInt32 const nCurrentParagraph =
5824 rPropReader.aCharPropList[rnCurCharPos]->mnParagraph;
5825 for (; rnCurCharPos < rPropReader.aCharPropList.size() &&
5826 rPropReader.aCharPropList[rnCurCharPos]->mnParagraph == nCurrentParagraph;
5827 ++rnCurCharPos)
5829 PPTCharPropSet *const pCharPropSet =
5830 rPropReader.aCharPropList[rnCurCharPos].get();
5831 std::unique_ptr<PPTPortionObj> pPPTPortion(new PPTPortionObj(
5832 *pCharPropSet, rStyleSheet, nInstance, mxParaSet->mnDepth));
5833 m_PortionList.push_back(std::move(pPPTPortion));
5837 PPTParagraphObj::~PPTParagraphObj()
5841 void PPTParagraphObj::AppendPortion( PPTPortionObj& rPPTPortion )
5843 m_PortionList.push_back(
5844 std::make_unique<PPTPortionObj>(rPPTPortion));
5847 void PPTParagraphObj::UpdateBulletRelSize( sal_uInt32& nBulletRelSize ) const
5849 if ( nBulletRelSize <= 0x7fff ) // a negative value is the absolute bullet height
5850 return;
5852 sal_uInt16 nFontHeight = 0;
5853 if (!m_PortionList.empty())
5855 PPTPortionObj const& rPortion = *m_PortionList.front();
5856 if (rPortion.mpImplPPTCharPropSet->mnAttrSet & (1 << PPT_CharAttr_FontHeight))
5858 nFontHeight = rPortion.mpImplPPTCharPropSet->mnFontHeight;
5861 // if we do not have a hard attributed fontheight, the fontheight is taken from the style
5862 if ( !nFontHeight )
5864 nFontHeight = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[sanitizeForMaxPPTLevels(mxParaSet->mnDepth)].mnFontHeight;
5866 nBulletRelSize = nFontHeight ? ((- static_cast<sal_Int16>(nBulletRelSize)) * 100 ) / nFontHeight : 100;
5869 bool PPTParagraphObj::GetAttrib( sal_uInt32 nAttr, sal_uInt32& rRetValue, TSS_Type nDestinationInstance )
5871 sal_uInt32 nMask = 1 << nAttr;
5872 rRetValue = 0;
5874 if ( nAttr > 21 )
5876 OSL_FAIL( "SJ:PPTParagraphObj::GetAttrib - attribute does not exist" );
5877 return false;
5880 bool bIsHardAttribute = ( ( mxParaSet->mnAttrSet & nMask ) != 0 );
5882 sal_uInt16 nDepth = sanitizeForMaxPPTLevels(mxParaSet->mnDepth);
5884 if ( bIsHardAttribute )
5886 if ( nAttr == PPT_ParaAttr_BulletColor )
5888 bool bHardBulletColor;
5889 if ( mxParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardColor ) )
5890 bHardBulletColor = mxParaSet->mpArry[ PPT_ParaAttr_BuHardColor ] != 0;
5891 else
5892 bHardBulletColor = ( mrStyleSheet.mpParaSheet[ mnInstance ]->maParaLevel[nDepth].mnBuFlags
5893 & ( 1 << PPT_ParaAttr_BuHardColor ) ) != 0;
5894 if ( bHardBulletColor )
5895 rRetValue = mxParaSet->mnBulletColor;
5896 else
5898 rRetValue = PPT_COLSCHEME_TEXT_UND_ZEILEN;
5899 if ((nDestinationInstance != TSS_Type::Unknown) && !m_PortionList.empty())
5901 PPTPortionObj const& rPortion = *m_PortionList.front();
5902 if (rPortion.mpImplPPTCharPropSet->mnAttrSet & (1 << PPT_CharAttr_FontColor))
5904 rRetValue = rPortion.mpImplPPTCharPropSet->mnColor;
5906 else
5908 rRetValue = mrStyleSheet.mpCharSheet[ nDestinationInstance ]->maCharLevel[nDepth].mnFontColor;
5913 else if ( nAttr == PPT_ParaAttr_BulletFont )
5915 bool bHardBuFont;
5916 if ( mxParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardFont ) )
5917 bHardBuFont = mxParaSet->mpArry[ PPT_ParaAttr_BuHardFont ] != 0;
5918 else
5919 bHardBuFont = ( mrStyleSheet.mpParaSheet[ mnInstance ]->maParaLevel[nDepth].mnBuFlags
5920 & ( 1 << PPT_ParaAttr_BuHardFont ) ) != 0;
5921 if ( bHardBuFont )
5922 rRetValue = mxParaSet->mpArry[ PPT_ParaAttr_BulletFont ];
5923 else
5925 // it is the font used which assigned to the first character of the following text
5926 rRetValue = 0;
5927 if ((nDestinationInstance != TSS_Type::Unknown) && !m_PortionList.empty())
5929 PPTPortionObj const& rPortion = *m_PortionList.front();
5930 if (rPortion.mpImplPPTCharPropSet->mnAttrSet & ( 1 << PPT_CharAttr_Font ) )
5932 rRetValue = rPortion.mpImplPPTCharPropSet->mnFont;
5934 else
5936 rRetValue = mrStyleSheet.mpCharSheet[ nDestinationInstance ]->maCharLevel[nDepth].mnFont;
5941 else
5942 rRetValue = mxParaSet->mpArry[ nAttr ];
5944 else
5946 const PPTParaLevel& rParaLevel = mrStyleSheet.mpParaSheet[ mnInstance ]->maParaLevel[nDepth];
5948 PPTParaLevel* pParaLevel = nullptr;
5949 if ( ( nDestinationInstance == TSS_Type::Unknown )
5950 || ( nDepth && ( ( mnInstance == TSS_Type::Subtitle ) || ( mnInstance == TSS_Type::TextInShape ) ) ) )
5951 bIsHardAttribute = true;
5952 else if ( nDestinationInstance != mnInstance )
5953 pParaLevel = &mrStyleSheet.mpParaSheet[ nDestinationInstance ]->maParaLevel[nDepth];
5954 switch ( nAttr )
5956 case PPT_ParaAttr_BulletOn :
5958 rRetValue = rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BulletOn );
5959 if ( pParaLevel )
5961 if ( rRetValue != ( static_cast<sal_uInt32>(pParaLevel->mnBuFlags) & ( 1 << PPT_ParaAttr_BulletOn ) ) )
5962 bIsHardAttribute = true;
5965 break;
5966 case PPT_ParaAttr_BuHardFont :
5967 case PPT_ParaAttr_BuHardColor :
5968 case PPT_ParaAttr_BuHardHeight :
5969 OSL_FAIL( "SJ:PPTParagraphObj::GetAttrib - this attribute does not make sense" );
5970 break;
5971 case PPT_ParaAttr_BulletChar :
5973 rRetValue = rParaLevel.mnBulletChar;
5974 if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletChar ) )
5975 bIsHardAttribute = true;
5977 break;
5978 case PPT_ParaAttr_BulletFont :
5980 bool bHardBuFont;
5981 if ( mxParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardFont ) )
5982 bHardBuFont = mxParaSet->mpArry[ PPT_ParaAttr_BuHardFont ] != 0;
5983 else
5984 bHardBuFont = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardFont ) ) != 0;
5985 if ( bHardBuFont )
5987 rRetValue = rParaLevel.mnBulletFont;
5988 if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletFont ) )
5989 bIsHardAttribute = true;
5991 else
5993 if (!m_PortionList.empty())
5995 PPTPortionObj const& rPortion = *m_PortionList.front();
5996 bIsHardAttribute = rPortion.GetAttrib(
5997 PPT_CharAttr_Font, rRetValue, nDestinationInstance);
5999 else
6001 rRetValue = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[nDepth].mnFont;
6002 bIsHardAttribute = true;
6006 break;
6007 case PPT_ParaAttr_BulletHeight :
6009 rRetValue = rParaLevel.mnBulletHeight;
6010 if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletHeight ) )
6011 bIsHardAttribute = true;
6013 break;
6014 case PPT_ParaAttr_BulletColor :
6016 bool bHardBulletColor;
6017 if ( mxParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardColor ) )
6018 bHardBulletColor = mxParaSet->mpArry[ PPT_ParaAttr_BuHardColor ] != 0;
6019 else
6020 bHardBulletColor = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardColor ) ) != 0;
6021 if ( bHardBulletColor )
6023 rRetValue = rParaLevel.mnBulletColor;
6024 if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletColor ) )
6025 bIsHardAttribute = true;
6027 else
6029 if (!m_PortionList.empty())
6031 PPTPortionObj const& rPortion = *m_PortionList.front();
6032 if (rPortion.mbIsHyperlink )
6034 if( rPortion.mbHardHylinkOrigColor )
6035 rRetValue = rPortion.mnHylinkOrigColor;
6036 else
6037 rRetValue = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[nDepth].mnFontColor;
6038 bIsHardAttribute = true;
6040 else
6042 bIsHardAttribute = rPortion.GetAttrib( PPT_CharAttr_FontColor, rRetValue, nDestinationInstance );
6045 else
6047 rRetValue = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[nDepth].mnFontColor;
6048 bIsHardAttribute = true;
6052 break;
6053 case PPT_ParaAttr_Adjust :
6055 rRetValue = rParaLevel.mnAdjust;
6056 if ( pParaLevel && ( rRetValue != pParaLevel->mnAdjust ) )
6057 bIsHardAttribute = true;
6059 break;
6060 case PPT_ParaAttr_LineFeed :
6062 rRetValue = rParaLevel.mnLineFeed;
6063 if ( pParaLevel && ( rRetValue != pParaLevel->mnLineFeed ) )
6064 bIsHardAttribute = true;
6066 break;
6067 case PPT_ParaAttr_UpperDist :
6069 rRetValue = rParaLevel.mnUpperDist;
6070 if ( pParaLevel && ( rRetValue != pParaLevel->mnUpperDist ) )
6071 bIsHardAttribute = true;
6073 break;
6074 case PPT_ParaAttr_LowerDist :
6076 rRetValue = rParaLevel.mnLowerDist;
6077 if ( pParaLevel && ( rRetValue != pParaLevel->mnLowerDist ) )
6078 bIsHardAttribute = true;
6080 break;
6081 case PPT_ParaAttr_TextOfs :
6083 rRetValue = rParaLevel.mnTextOfs;
6084 if ( pParaLevel && ( rRetValue != pParaLevel->mnTextOfs ) )
6085 bIsHardAttribute = true;
6087 break;
6088 case PPT_ParaAttr_BulletOfs :
6090 rRetValue = rParaLevel.mnBulletOfs;
6091 if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletOfs ) )
6092 bIsHardAttribute = true;
6094 break;
6095 case PPT_ParaAttr_DefaultTab :
6097 rRetValue = rParaLevel.mnDefaultTab;
6098 if ( pParaLevel && ( rRetValue != pParaLevel->mnDefaultTab ) )
6099 bIsHardAttribute = true;
6101 break;
6102 case PPT_ParaAttr_AsianLB_1 :
6104 rRetValue = rParaLevel.mnAsianLineBreak & 1;
6105 if ( pParaLevel && ( rRetValue != ( static_cast<sal_uInt32>(pParaLevel->mnAsianLineBreak) & 1 ) ) )
6106 bIsHardAttribute = true;
6108 break;
6109 case PPT_ParaAttr_AsianLB_2 :
6111 rRetValue = ( rParaLevel.mnAsianLineBreak >> 1 ) & 1;
6112 if ( pParaLevel && ( rRetValue != ( ( static_cast<sal_uInt32>(pParaLevel->mnAsianLineBreak) >> 1 ) & 1 ) ) )
6113 bIsHardAttribute = true;
6115 break;
6116 case PPT_ParaAttr_AsianLB_3 :
6118 rRetValue = ( rParaLevel.mnAsianLineBreak >> 2 ) & 1;
6119 if ( pParaLevel && ( rRetValue != ( ( static_cast<sal_uInt32>(pParaLevel->mnAsianLineBreak) >> 2 ) & 1 ) ) )
6120 bIsHardAttribute = true;
6122 break;
6123 case PPT_ParaAttr_BiDi :
6125 rRetValue = rParaLevel.mnBiDi;
6126 if ( pParaLevel && ( rRetValue != pParaLevel->mnBiDi ) )
6127 bIsHardAttribute = true;
6129 break;
6132 return bIsHardAttribute;
6135 void PPTParagraphObj::ApplyTo( SfxItemSet& rSet, std::optional< sal_Int16 >& rStartNumbering, SdrPowerPointImport const & rManager, TSS_Type nDestinationInstance )
6137 sal_Int16 nVal2;
6138 sal_uInt32 nVal, nUpperDist, nLowerDist;
6139 TSS_Type nInstance = nDestinationInstance != TSS_Type::Unknown ? nDestinationInstance : mnInstance;
6141 if ( ( nDestinationInstance != TSS_Type::Unknown ) || ( mxParaSet->mnDepth <= 1 ) )
6143 SvxNumBulletItem* pNumBulletItem = mrStyleSheet.mpNumBulletItem[ nInstance ].get();
6144 if ( pNumBulletItem )
6146 SvxNumberFormat aNumberFormat( SVX_NUM_NUMBER_NONE );
6147 if ( GetNumberFormat( rManager, aNumberFormat, this, nDestinationInstance, rStartNumbering ) )
6149 if ( aNumberFormat.GetNumberingType() == SVX_NUM_NUMBER_NONE )
6151 aNumberFormat.SetAbsLSpace( 0 );
6152 aNumberFormat.SetFirstLineOffset( 0 );
6153 aNumberFormat.SetCharTextDistance( 0 );
6154 aNumberFormat.SetFirstLineIndent( 0 );
6155 aNumberFormat.SetIndentAt( 0 );
6157 SvxNumBulletItem aNewNumBulletItem( *pNumBulletItem );
6158 SvxNumRule& rRule = aNewNumBulletItem.GetNumRule();
6159 rRule.SetLevel( mxParaSet->mnDepth, aNumberFormat );
6160 for (sal_uInt16 i = 0; i < rRule.GetLevelCount(); ++i)
6162 if ( i != mxParaSet->mnDepth )
6164 sal_uInt16 n = sanitizeForMaxPPTLevels(i);
6166 SvxNumberFormat aNumberFormat2( rRule.GetLevel( i ) );
6167 const PPTParaLevel& rParaLevel = mrStyleSheet.mpParaSheet[ nInstance ]->maParaLevel[ n ];
6168 const PPTCharLevel& rCharLevel = mrStyleSheet.mpCharSheet[ nInstance ]->maCharLevel[ n ];
6169 sal_uInt32 nColor;
6170 if ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardColor ) )
6171 nColor = rParaLevel.mnBulletColor;
6172 else
6173 nColor = rCharLevel.mnFontColor;
6174 aNumberFormat2.SetBulletColor( rManager.MSO_TEXT_CLR_ToColor( nColor ) );
6175 rRule.SetLevel( i, aNumberFormat2 );
6178 rSet.Put( aNewNumBulletItem );
6183 sal_uInt32 nIsBullet2, _nTextOfs, _nBulletOfs;
6184 GetAttrib(PPT_ParaAttr_BulletOn, nIsBullet2, nDestinationInstance);
6185 GetAttrib(PPT_ParaAttr_TextOfs, _nTextOfs, nDestinationInstance);
6186 GetAttrib(PPT_ParaAttr_BulletOfs, _nBulletOfs, nDestinationInstance);
6187 SvxLRSpaceItem aLRSpaceItem( EE_PARA_LRSPACE );
6188 if ( !nIsBullet2 )
6190 auto const nAbsLSpace = convertMasterUnitToMm100(_nTextOfs);
6191 auto const nFirstLineOffset = nAbsLSpace - convertMasterUnitToMm100(_nBulletOfs);
6192 aLRSpaceItem.SetTextFirstLineOffsetValue( -nFirstLineOffset );
6193 aLRSpaceItem.SetTextLeft( nAbsLSpace );
6195 rSet.Put( aLRSpaceItem );
6197 if ( GetAttrib( PPT_ParaAttr_Adjust, nVal, nDestinationInstance ) )
6199 if ( nVal <= 3 )
6200 { // paragraph adjustment
6201 static SvxAdjust const aAdj[ 4 ] = { SvxAdjust::Left, SvxAdjust::Center, SvxAdjust::Right, SvxAdjust::Block };
6202 rSet.Put( SvxAdjustItem( aAdj[ nVal ], EE_PARA_JUST ) );
6206 if ( GetAttrib( PPT_ParaAttr_AsianLB_1, nVal, nDestinationInstance ) )
6207 rSet.Put(SvxForbiddenRuleItem(nVal != 0, EE_PARA_FORBIDDENRULES));
6208 if ( GetAttrib( PPT_ParaAttr_AsianLB_3, nVal, nDestinationInstance ) )
6209 rSet.Put(SvxHangingPunctuationItem(nVal != 0, EE_PARA_HANGINGPUNCTUATION));
6211 if ( GetAttrib( PPT_ParaAttr_BiDi, nVal, nDestinationInstance ) )
6212 rSet.Put( SvxFrameDirectionItem( nVal == 1 ? SvxFrameDirection::Horizontal_RL_TB : SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ) );
6214 // LineSpacing
6215 PPTPortionObj* pPortion = First();
6216 bool bIsHardAttribute = GetAttrib( PPT_ParaAttr_LineFeed, nVal, nDestinationInstance );
6217 nVal2 = static_cast<sal_Int16>(nVal);
6218 sal_uInt32 nFont = sal_uInt32();
6219 if ( pPortion && pPortion->GetAttrib( PPT_CharAttr_Font, nFont, nDestinationInstance ) )
6220 bIsHardAttribute = true;
6222 if ( bIsHardAttribute )
6224 SdrTextFixedCellHeightItem aHeightItem(true);
6225 aHeightItem.SetWhich(SDRATTR_TEXT_USEFIXEDCELLHEIGHT);
6226 rSet.Put( aHeightItem );
6227 SvxLineSpacingItem aItem( 200, EE_PARA_SBL );
6228 if ( nVal2 <= 0 ) {
6229 aItem.SetLineHeight( static_cast<sal_uInt16>( rManager.ScalePoint( -nVal2 ) / 8 ) );
6230 aItem.SetLineSpaceRule( SvxLineSpaceRule::Fix );
6231 aItem.SetInterLineSpaceRule(SvxInterLineSpaceRule::Off);
6232 } else
6234 sal_uInt16 nPropLineSpace = static_cast<sal_uInt16>(nVal2);
6235 aItem.SetPropLineSpace( nPropLineSpace );
6236 aItem.SetLineSpaceRule( SvxLineSpaceRule::Auto );
6238 rSet.Put( aItem );
6241 // Paragraph Spacing
6242 bIsHardAttribute = ( static_cast<sal_uInt32>(GetAttrib( PPT_ParaAttr_UpperDist, nUpperDist, nDestinationInstance )) +
6243 static_cast<sal_uInt32>(GetAttrib( PPT_ParaAttr_LowerDist, nLowerDist, nDestinationInstance )) ) != 0;
6244 if ( ( nUpperDist > 0 ) || ( nLowerDist > 0 ) )
6246 if (!m_PortionList.empty())
6248 sal_uInt32 nFontHeight = 0;
6249 m_PortionList.back()->GetAttrib(
6250 PPT_CharAttr_FontHeight, nFontHeight, nDestinationInstance);
6251 if ( static_cast<sal_Int16>(nUpperDist) > 0 )
6252 nUpperDist = - static_cast<sal_Int16>( ( nFontHeight * nUpperDist * 100 ) / 1000 );
6253 if ( static_cast<sal_Int16>(nLowerDist) > 0 )
6254 nLowerDist = - static_cast<sal_Int16>( ( nFontHeight * nLowerDist * 100 ) / 1000 );
6256 bIsHardAttribute = true;
6258 if ( bIsHardAttribute )
6260 SvxULSpaceItem aULSpaceItem( EE_PARA_ULSPACE );
6261 nVal2 = static_cast<sal_Int16>(nUpperDist);
6262 if ( nVal2 <= 0 )
6263 aULSpaceItem.SetUpper(static_cast<sal_uInt16>(convertMasterUnitToMm100(-nVal2)));
6264 else
6266 aULSpaceItem.SetUpperValue( 0 );
6267 aULSpaceItem.SetPropUpper( static_cast<sal_uInt16>(nUpperDist) == 100 ? 101 : static_cast<sal_uInt16>(nUpperDist) );
6269 nVal2 = static_cast<sal_Int16>(nLowerDist);
6270 if ( nVal2 <= 0 )
6271 aULSpaceItem.SetLower(static_cast<sal_uInt16>(convertMasterUnitToMm100(-nVal2)));
6272 else
6274 aULSpaceItem.SetLowerValue( 0 );
6275 aULSpaceItem.SetPropLower( static_cast<sal_uInt16>(nLowerDist) == 100 ? 101 : static_cast<sal_uInt16>(nLowerDist) );
6277 rSet.Put( aULSpaceItem );
6280 sal_uInt32 i, nDefaultTab, nTab, nTextOfs2 = 0;
6281 sal_uInt32 nLatestManTab = 0;
6282 GetAttrib( PPT_ParaAttr_TextOfs, nTextOfs2, nDestinationInstance );
6283 GetAttrib( PPT_ParaAttr_BulletOfs, nTab, nDestinationInstance );
6284 GetAttrib( PPT_ParaAttr_DefaultTab, nDefaultTab, nDestinationInstance );
6286 SvxTabStopItem aTabItem( 0, 0, SvxTabAdjust::Default, EE_PARA_TABS );
6287 if ( GetTabCount() )
6289 for ( i = 0; i < GetTabCount(); i++ )
6291 SvxTabAdjust eTabAdjust;
6292 nTab = GetTabOffsetByIndex( static_cast<sal_uInt16>(i) );
6293 switch( GetTabStyleByIndex( static_cast<sal_uInt16>(i) ) )
6295 case 1 : eTabAdjust = SvxTabAdjust::Center; break;
6296 case 2 : eTabAdjust = SvxTabAdjust::Right; break;
6297 case 3 : eTabAdjust = SvxTabAdjust::Decimal; break;
6298 default : eTabAdjust = SvxTabAdjust::Left;
6300 aTabItem.Insert(SvxTabStop(convertMasterUnitToMm100(nTab), eTabAdjust));
6302 nLatestManTab = nTab;
6304 if ( nIsBullet2 == 0 )
6305 aTabItem.Insert( SvxTabStop( sal_uInt16(0) ) );
6306 if ( nDefaultTab )
6308 nTab = std::max( nTextOfs2, nLatestManTab );
6309 nTab /= nDefaultTab;
6310 nTab = nDefaultTab * ( 1 + nTab );
6311 for ( i = 0; ( i < 20 ) && ( nTab < 0x1b00 ); i++ )
6313 aTabItem.Insert( SvxTabStop( convertMasterUnitToMm100(nTab)));
6314 nTab += nDefaultTab;
6317 rSet.Put( aTabItem );
6320 sal_uInt32 PPTParagraphObj::GetTextSize()
6322 sal_uInt32 nCount, nRetValue = 0;
6323 for (const std::unique_ptr<PPTPortionObj> & i : m_PortionList)
6325 PPTPortionObj const& rPortionObj = *i;
6326 nCount = rPortionObj.Count();
6327 if ((!nCount) && rPortionObj.mpFieldItem)
6328 nCount++;
6329 nRetValue += nCount;
6331 return nRetValue;
6334 PPTPortionObj* PPTParagraphObj::First()
6336 mnCurrentObject = 0;
6337 if (m_PortionList.empty())
6338 return nullptr;
6339 return m_PortionList.front().get();
6342 PPTPortionObj* PPTParagraphObj::Next()
6344 sal_uInt32 i = mnCurrentObject + 1;
6345 if (i >= m_PortionList.size())
6346 return nullptr;
6347 mnCurrentObject++;
6348 return m_PortionList[i].get();
6351 PPTFieldEntry::~PPTFieldEntry()
6355 void PPTFieldEntry::GetDateTime( const sal_uInt32 nVal, SvxDateFormat& eDateFormat, SvxTimeFormat& eTimeFormat )
6357 eDateFormat = SvxDateFormat::AppDefault;
6358 eTimeFormat = SvxTimeFormat::AppDefault;
6359 // evaluate ID
6360 switch( nVal )
6362 case 0:
6363 case 6:
6364 eDateFormat = SvxDateFormat::A;
6365 break;
6366 case 1:
6367 eDateFormat = SvxDateFormat::F;
6368 break;
6369 case 2:
6370 case 3:
6371 eDateFormat = SvxDateFormat::D;
6372 break;
6373 case 4:
6374 case 5:
6375 eDateFormat = SvxDateFormat::C;
6376 break;
6377 case 7:
6378 eDateFormat = SvxDateFormat::A;
6379 [[fallthrough]];
6380 case 9:
6381 eTimeFormat = SvxTimeFormat::HH24_MM;
6382 break;
6383 case 8:
6384 eDateFormat = SvxDateFormat::A;
6385 [[fallthrough]];
6386 case 11:
6387 eTimeFormat = SvxTimeFormat::HH12_MM;
6388 break;
6389 case 10:
6390 eTimeFormat = SvxTimeFormat::HH24_MM_SS;
6391 break;
6392 case 12:
6393 eTimeFormat = SvxTimeFormat::HH12_MM_SS;
6394 break;
6398 void PPTFieldEntry::SetDateTime( sal_uInt32 nVal )
6400 SvxDateFormat eDateFormat;
6401 SvxTimeFormat eTimeFormat;
6402 GetDateTime( nVal, eDateFormat, eTimeFormat );
6403 if ( eDateFormat != SvxDateFormat::AppDefault )
6404 xField1.reset(new SvxFieldItem(SvxDateField( Date( Date::SYSTEM ), SvxDateType::Var, eDateFormat ), EE_FEATURE_FIELD));
6405 if ( eTimeFormat != SvxTimeFormat::AppDefault )
6407 std::unique_ptr<SvxFieldItem> xFieldItem(new SvxFieldItem(SvxExtTimeField( tools::Time( tools::Time::SYSTEM ), SvxTimeType::Var, eTimeFormat ), EE_FEATURE_FIELD));
6408 if (xField1)
6409 xField2 = std::move(xFieldItem);
6410 else
6411 xField1 = std::move(xFieldItem);
6415 PPTTextObj::PPTTextObj( SvStream& rIn, SdrPowerPointImport& rSdrPowerPointImport, PptSlidePersistEntry& rPersistEntry, DffObjData const * pObjData ) :
6416 mxImplTextObj ( new ImplPPTTextObj( rPersistEntry ) )
6418 mxImplTextObj->mnShapeId = 0;
6419 mxImplTextObj->mnShapeMaster = 0;
6420 mxImplTextObj->mnDestinationInstance = mxImplTextObj->mnInstance = TSS_Type::TextInShape;
6421 mxImplTextObj->mnCurrentObject = 0;
6422 mxImplTextObj->mnParagraphCount = 0;
6423 mxImplTextObj->mnTextFlags = 0;
6424 mxImplTextObj->meShapeType = ( pObjData && pObjData->bShapeType ) ? pObjData->eShapeType : mso_sptMin;
6426 DffRecordHeader aExtParaHd;
6427 aExtParaHd.nRecType = 0; // set empty
6430 DffRecordHeader aShapeContainerHd;
6431 ReadDffRecordHeader( rIn, aShapeContainerHd );
6433 if ( !(( pObjData == nullptr ) || ( pObjData->bShapeType )) )
6434 return;
6436 PPTExtParaProv* pExtParaProv = rSdrPowerPointImport.m_pPPTStyleSheet->pExtParaProv.get();
6437 if ( pObjData )
6439 mxImplTextObj->mnShapeId = pObjData->nShapeId;
6440 if ( pObjData->nSpFlags & ShapeFlag::HaveMaster )
6441 mxImplTextObj->mnShapeMaster = rSdrPowerPointImport.GetPropertyValue( DFF_Prop_hspMaster, 0 );
6443 // ClientData
6444 if ( rSdrPowerPointImport.maShapeRecords.SeekToContent( rIn, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) )
6446 sal_uInt32 nOldPos = rIn.Tell();
6447 DffRecordHeader& aClientDataContainerHd = *rSdrPowerPointImport.maShapeRecords.Current();
6448 DffRecordHeader aPlaceHolderAtomHd;
6449 if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_OEPlaceholderAtom, aClientDataContainerHd.GetRecEndFilePos(), &aPlaceHolderAtomHd ) )
6451 mxImplTextObj->moPlaceHolderAtom.emplace();
6452 ReadPptOEPlaceholderAtom( rIn, *( mxImplTextObj->moPlaceHolderAtom ) );
6454 rIn.Seek( nOldPos );
6455 DffRecordHeader aProgTagHd;
6456 if ( SdrPowerPointImport::SeekToContentOfProgTag( 9, rIn, aClientDataContainerHd, aProgTagHd ) )
6458 ReadDffRecordHeader( rIn, aExtParaHd );
6462 // ClientTextBox
6463 if ( !rSdrPowerPointImport.maShapeRecords.SeekToContent( rIn, DFF_msofbtClientTextbox, SEEK_FROM_CURRENT_AND_RESTART ) )
6464 return;
6466 bool bStatus = true;
6469 DffRecordHeader aClientTextBoxHd( *rSdrPowerPointImport.maShapeRecords.Current() );
6470 sal_uInt32 nTextRulerAtomOfs = 0; // case of zero -> this atom may be found in aClientDataContainerHd;
6471 // case of -1 -> there is no atom of this kind
6472 // else -> this is the fileofs where we can get it
6474 // checkout if this is a referenced
6475 // textobj, if so the we will patch
6476 // the ClientTextBoxHd for a
6477 // equivalent one
6478 DffRecordHeader aTextHd;
6479 if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_OutlineTextRefAtom, aClientTextBoxHd.GetRecEndFilePos(), &aTextHd ) )
6481 sal_uInt32 nRefNum;
6482 rIn.ReadUInt32( nRefNum );
6484 if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_TextRulerAtom, aClientTextBoxHd.GetRecEndFilePos() ) )
6485 nTextRulerAtomOfs = rIn.Tell();
6486 else
6487 nTextRulerAtomOfs = 0xffffffff;
6489 switch( rSdrPowerPointImport.m_eCurrentPageKind )
6491 case PPT_NOTEPAGE :
6492 case PPT_MASTERPAGE :
6493 case PPT_SLIDEPAGE :
6494 break;
6495 default :
6496 bStatus = false;
6498 if ( bStatus )
6500 sal_uInt32 nSlideId = rSdrPowerPointImport.GetCurrentPageId();
6501 if ( !nSlideId )
6502 bStatus = false;
6503 else
6505 if ( !aExtParaHd.nRecType )
6507 sal_uInt32 nOldPos = rIn.Tell();
6508 // try to locate the referenced ExtendedParaHd
6509 DffRecordHeader* pHd = pExtParaProv->
6510 aExtendedPresRules.GetRecordHeader( PPT_PST_ExtendedParagraphHeaderAtom,
6511 SEEK_FROM_CURRENT_AND_RESTART );
6512 DffRecordHeader aPresRuleHd;
6513 DffRecordHeader* pFirst = pHd;
6515 while ( pHd )
6517 pHd->SeekToContent( rIn );
6518 sal_uInt32 nTmpSlideId(0), nTmpRef;
6519 rIn.ReadUInt32( nTmpSlideId )
6520 .ReadUInt32( nTmpRef ); // this seems to be the instance
6522 if ( ( nTmpSlideId == nSlideId ) && ( pHd->nRecInstance == nRefNum ) )
6524 if (!pHd->SeekToEndOfRecord(rIn))
6525 break;
6526 ReadDffRecordHeader( rIn, aPresRuleHd );
6527 if ( aPresRuleHd.nRecType == PPT_PST_ExtendedParagraphAtom )
6529 aExtParaHd = aPresRuleHd;
6530 break;
6533 pHd = pExtParaProv->
6534 aExtendedPresRules.GetRecordHeader( PPT_PST_ExtendedParagraphHeaderAtom,
6535 SEEK_FROM_CURRENT_AND_RESTART );
6536 if ( pHd == pFirst )
6537 break;
6539 rIn.Seek( nOldPos );
6541 // now pHd points to the right SlideListWithText Container
6542 PptSlidePersistList* pPageList = rSdrPowerPointImport.GetPageList( rSdrPowerPointImport.m_eCurrentPageKind );
6543 PptSlidePersistEntry* pE = nullptr;
6544 if ( pPageList && ( rSdrPowerPointImport.m_nCurrentPageNum < pPageList->size() ) )
6545 pE = &(*pPageList)[ rSdrPowerPointImport.m_nCurrentPageNum ];
6546 if ( (!pE) || (!pE->nSlidePersistStartOffset) || ( pE->aPersistAtom.nSlideId != nSlideId ) )
6547 bStatus = false;
6548 else
6550 auto nOffset(pE->nSlidePersistStartOffset);
6551 bStatus = (nOffset == rIn.Seek(nOffset));
6552 // now we got the right page and are searching for the right
6553 // TextHeaderAtom
6554 auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, pE->nSlidePersistEndOffset);
6555 while (bStatus && rIn.Tell() < nEndRecPos)
6557 ReadDffRecordHeader( rIn, aClientTextBoxHd );
6558 if ( aClientTextBoxHd.nRecType == PPT_PST_TextHeaderAtom )
6560 if ( aClientTextBoxHd.nRecInstance == nRefNum )
6562 aClientTextBoxHd.SeekToEndOfRecord( rIn );
6563 break;
6566 if (!aClientTextBoxHd.SeekToEndOfRecord(rIn))
6567 break;
6569 if ( rIn.Tell() > pE->nSlidePersistEndOffset )
6570 bStatus = false;
6571 else
6572 { // patching the RecordHeader
6573 aClientTextBoxHd.nFilePos -= DFF_COMMON_RECORD_HEADER_SIZE;
6574 aClientTextBoxHd.nRecLen += DFF_COMMON_RECORD_HEADER_SIZE;
6575 aClientTextBoxHd.nRecType = DFF_msofbtClientTextbox;
6576 aClientTextBoxHd.nRecVer = DFF_PSFLAG_CONTAINER;
6578 // we have to calculate the correct record len
6579 DffRecordHeader aTmpHd;
6580 nEndRecPos = DffPropSet::SanitizeEndPos(rIn, pE->nSlidePersistEndOffset);
6581 while (rIn.Tell() < nEndRecPos)
6583 ReadDffRecordHeader( rIn, aTmpHd );
6584 if ( ( aTmpHd.nRecType == PPT_PST_SlidePersistAtom ) || ( aTmpHd.nRecType == PPT_PST_TextHeaderAtom ) )
6585 break;
6586 if (!aTmpHd.SeekToEndOfRecord(rIn))
6587 break;
6588 aClientTextBoxHd.nRecLen += aTmpHd.nRecLen + DFF_COMMON_RECORD_HEADER_SIZE;
6590 aClientTextBoxHd.SeekToContent( rIn );
6597 if ( !bStatus )
6598 return;
6600 if ( !SvxMSDffManager::SeekToRec( rIn, PPT_PST_TextHeaderAtom, aClientTextBoxHd.GetRecEndFilePos(), &aTextHd ) )
6601 return;
6603 // TextHeaderAtom is always the first Atom
6604 sal_uInt16 nTmp(0);
6605 rIn.ReadUInt16(nTmp); // this number tells us the TxMasterStyleAtom Instance
6606 if (nTmp > 8)
6607 nTmp = 4;
6608 TSS_Type nInstance = static_cast<TSS_Type>(nTmp);
6609 aTextHd.SeekToEndOfRecord( rIn );
6610 mxImplTextObj->mnInstance = nInstance;
6612 sal_uInt32 nFilePos = rIn.Tell();
6613 if ( !(rSdrPowerPointImport.SeekToRec2( PPT_PST_TextBytesAtom,
6614 PPT_PST_TextCharsAtom,
6615 aClientTextBoxHd.GetRecEndFilePos() )
6616 || SvxMSDffManager::SeekToRec( rIn,
6617 PPT_PST_StyleTextPropAtom,
6618 aClientTextBoxHd.GetRecEndFilePos() )) )
6619 return;
6621 PPTTextRulerInterpreter aTextRulerInterpreter( nTextRulerAtomOfs, aClientTextBoxHd, rIn );
6623 PPTStyleTextPropReader aStyleTextPropReader( rIn, aClientTextBoxHd,
6624 aTextRulerInterpreter, aExtParaHd, nInstance );
6625 sal_uInt32 nParagraphs = mxImplTextObj->mnParagraphCount = aStyleTextPropReader.aParaPropList.size();
6626 if ( !nParagraphs )
6627 return;
6629 // the language settings will be merged into the list of PPTCharPropSet
6630 DffRecordHeader aTextSpecInfoHd;
6631 PPTTextSpecInfoAtomInterpreter aTextSpecInfoAtomInterpreter;
6632 if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_TextSpecInfoAtom,
6633 aClientTextBoxHd.GetRecEndFilePos(), &aTextSpecInfoHd ) )
6635 if ( aTextSpecInfoAtomInterpreter.Read( rIn, aTextSpecInfoHd, PPT_PST_TextSpecInfoAtom,
6636 &(rSdrPowerPointImport.m_pPPTStyleSheet->maTxSI) ) )
6638 size_t nI = 0;
6639 for (const PPTTextSpecInfo& rSpecInfo : aTextSpecInfoAtomInterpreter.aList)
6641 sal_uInt32 nCharIdx = rSpecInfo.nCharIdx;
6643 // portions and text have to been split in some cases
6644 for ( ; nI < aStyleTextPropReader.aCharPropList.size(); ++nI)
6646 PPTCharPropSet* pSet = aStyleTextPropReader.aCharPropList[nI].get();
6647 if (pSet->mnOriginalTextPos >= nCharIdx)
6648 break;
6649 pSet->mnLanguage[0] = rSpecInfo.nLanguage[0];
6650 pSet->mnLanguage[1] = rSpecInfo.nLanguage[1];
6651 pSet->mnLanguage[2] = rSpecInfo.nLanguage[2];
6652 // test if the current portion needs to be split
6653 if (pSet->maString.getLength() <= 1)
6654 continue;
6655 sal_Int32 nIndexOfNextPortion = pSet->maString.getLength() + pSet->mnOriginalTextPos;
6656 sal_Int32 nNewLen = nIndexOfNextPortion - nCharIdx;
6657 if (nNewLen <= 0)
6658 continue;
6659 sal_Int32 nOldLen = pSet->maString.getLength() - nNewLen;
6660 if (nOldLen <= 0)
6661 continue;
6662 OUString aString(pSet->maString);
6663 PPTCharPropSet* pNew = new PPTCharPropSet(*pSet);
6664 pSet->maString = aString.copy(0, nOldLen);
6665 pNew->maString = aString.copy(nOldLen, nNewLen);
6666 pNew->mnOriginalTextPos += nOldLen;
6667 aStyleTextPropReader.aCharPropList.emplace(aStyleTextPropReader.aCharPropList.begin() + nI + 1, pNew);
6671 #ifdef DBG_UTIL
6672 else
6674 if (!(rSdrPowerPointImport.rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT))
6676 OSL_FAIL( "SdrTextSpecInfoAtomInterpreter::Ctor(): parsing error, this document needs to be analysed (SJ)" );
6679 #endif
6681 // now will search for possible textextensions such as date/time fields
6682 // or ParaTabStops and append them on this textobj
6683 rIn.Seek( nFilePos );
6684 ::std::vector< std::unique_ptr<PPTFieldEntry> > FieldList;
6685 auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, aClientTextBoxHd.GetRecEndFilePos());
6686 while (rIn.Tell() < nEndRecPos)
6688 ReadDffRecordHeader( rIn, aTextHd );
6689 sal_uInt16 nVal = 0;
6690 std::unique_ptr<PPTFieldEntry> xEntry;
6691 switch ( aTextHd.nRecType )
6693 case PPT_PST_DateTimeMCAtom :
6695 xEntry.reset(new PPTFieldEntry);
6696 rIn.ReadUInt16(xEntry->nPos)
6697 .ReadUInt16( nVal )
6698 .ReadUInt16( nVal );
6699 xEntry->SetDateTime( nVal & 0xff );
6701 break;
6703 case PPT_PST_FooterMCAtom :
6705 xEntry.reset(new PPTFieldEntry);
6706 rIn.ReadUInt16(xEntry->nPos);
6707 xEntry->xField1.reset(new SvxFieldItem(SvxFooterField(), EE_FEATURE_FIELD));
6709 break;
6711 case PPT_PST_HeaderMCAtom :
6713 xEntry.reset(new PPTFieldEntry);
6714 rIn.ReadUInt16(xEntry->nPos);
6715 xEntry->xField1.reset(new SvxFieldItem(SvxHeaderField(), EE_FEATURE_FIELD));
6717 break;
6719 case PPT_PST_GenericDateMCAtom :
6721 xEntry.reset(new PPTFieldEntry);
6722 rIn.ReadUInt16(xEntry->nPos);
6723 xEntry->xField1.reset(new SvxFieldItem(SvxDateTimeField(), EE_FEATURE_FIELD));
6724 if (rPersistEntry.xHeaderFooterEntry) // sj: #i34111# on master pages it is possible
6725 { // that there is no HeaderFooterEntry available
6726 if (rPersistEntry.xHeaderFooterEntry->nAtom & 0x20000) // auto date time
6727 xEntry->SetDateTime(rPersistEntry.xHeaderFooterEntry->nAtom & 0xff);
6728 else
6729 xEntry->xString = rPersistEntry.xHeaderFooterEntry->pPlaceholder[nVal];
6732 break;
6734 case PPT_PST_SlideNumberMCAtom :
6735 case PPT_PST_RTFDateTimeMCAtom :
6737 xEntry.reset(new PPTFieldEntry);
6738 if ( aTextHd.nRecLen >= 4 )
6740 rIn.ReadUInt16(xEntry->nPos)
6741 .ReadUInt16( nVal );
6743 // evaluate ID
6744 //SvxFieldItem* pFieldItem = NULL;
6745 switch( aTextHd.nRecType )
6747 case PPT_PST_SlideNumberMCAtom:
6748 xEntry->xField1.reset(new SvxFieldItem(SvxPageField(), EE_FEATURE_FIELD));
6749 break;
6751 case PPT_PST_RTFDateTimeMCAtom:
6753 // Rude workaround for one special case reported
6754 // by a customer. (#i75203#)
6756 // Don't even attempt to handle the general use
6757 // case for PPT_PST_RTFDateTimeMCAtom (a generic
6758 // MS style date/time format string). Just handle
6759 // the special case where the format string
6760 // contains only one or several possibly empty
6761 // quoted strings. I.e. something that doesn't
6762 // expand to any date or time at all, but to a
6763 // fixed string. How on earth somebody manages to
6764 // produce such things in PPT slides I have no
6765 // idea.
6766 if (nVal == 0)
6768 OUStringBuffer aStr;
6769 bool inquote = false;
6770 for (int nLen = 0; nLen < 64; ++nLen)
6772 sal_Unicode n(0);
6773 rIn.ReadUtf16( n );
6775 // Collect quoted characters into aStr
6776 if ( n == '\'')
6777 inquote = !inquote;
6778 else if (!n)
6780 // End of format string
6781 xEntry->xString = aStr.makeStringAndClear();
6782 break;
6784 else if (!inquote)
6786 // Non-quoted character, i.e. a real
6787 // format specifier. We don't handle
6788 // those. Sorry.
6789 break;
6791 else
6793 aStr.append(OUStringChar(n));
6797 if (!xEntry->xString)
6799 // Handle as previously
6800 xEntry->xField1.reset(new SvxFieldItem( SvxDateField( Date( Date::SYSTEM ), SvxDateType::Fix ), EE_FEATURE_FIELD ));
6806 break;
6808 case PPT_PST_InteractiveInfo :
6810 DffRecordHeader aHdInteractiveInfoAtom;
6811 if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_InteractiveInfoAtom, aTextHd.GetRecEndFilePos(), &aHdInteractiveInfoAtom ) )
6813 PptInteractiveInfoAtom aInteractiveInfoAtom;
6814 ReadPptInteractiveInfoAtom( rIn, aInteractiveInfoAtom );
6815 for (const SdHyperlinkEntry& rHyperlink : rSdrPowerPointImport.m_aHyperList)
6817 if ( rHyperlink.nIndex == aInteractiveInfoAtom.nExHyperlinkId )
6819 if (!aTextHd.SeekToEndOfRecord(rIn))
6821 break;
6823 ReadDffRecordHeader( rIn, aTextHd );
6824 if ( aTextHd.nRecType != PPT_PST_TxInteractiveInfoAtom )
6826 aTextHd.SeekToBegOfRecord( rIn );
6827 continue;
6829 else
6831 sal_uInt32 nStartPos, nEndPos;
6832 rIn.ReadUInt32( nStartPos )
6833 .ReadUInt32( nEndPos );
6834 if ( nEndPos )
6836 xEntry.reset(new PPTFieldEntry);
6837 xEntry->nPos = static_cast<sal_uInt16>(nStartPos);
6838 xEntry->nTextRangeEnd = static_cast<sal_uInt16>(nEndPos);
6839 OUString aTarget( rHyperlink.aTarget );
6840 if ( !rHyperlink.aConvSubString.isEmpty() )
6842 aTarget += "#" + rHyperlink.aConvSubString;
6844 xEntry->xField1.reset(new SvxFieldItem( SvxURLField( aTarget, OUString(), SvxURLFormat::Repr ), EE_FEATURE_FIELD ));
6847 break;
6852 break;
6854 if (!aTextHd.SeekToEndOfRecord(rIn))
6855 break;
6856 if (xEntry)
6858 // sorting fields ( hi >> lo )
6859 auto it = std::find_if(FieldList.begin(), FieldList.end(),
6860 [&xEntry](const std::unique_ptr<PPTFieldEntry>& rxField) {
6861 return rxField->nPos < xEntry->nPos; });
6862 if ( it != FieldList.end() ) {
6863 FieldList.insert(it, std::move(xEntry));
6864 } else {
6865 FieldList.push_back( std::move(xEntry));
6869 if ( !FieldList.empty() )
6871 auto FE = FieldList.begin();
6872 auto& aCharPropList = aStyleTextPropReader.aCharPropList;
6874 sal_Int32 i = nParagraphs - 1;
6875 sal_Int32 n = aCharPropList.size() - 1;
6877 // at this point we just have a list of textportions(aCharPropList)
6878 // the next while loop tries to resolve the list of fields(pFieldList)
6879 while( ( FE < FieldList.end() ) && ( n >= 0 ) && ( i >= 0 ) )
6881 PPTCharPropSet* pSet = aCharPropList[n].get();
6882 OUString aString( pSet->maString );
6883 sal_uInt32 nCount = aString.getLength();
6884 sal_uInt32 nPos = pSet->mnOriginalTextPos + nCount;
6885 while ( ( FE < FieldList.end() ) && nCount-- )
6887 nPos--;
6888 FE = std::find_if(FE, FieldList.end(),
6889 [&nPos](const std::unique_ptr<PPTFieldEntry>& rxField) {return rxField->nPos <= nPos;});
6890 if (FE == FieldList.end())
6891 break;
6893 if ( (*FE)->nPos == nPos )
6895 if ( aString[nCount] == 0x2a )
6897 sal_uInt32 nBehind = aString.getLength() - ( nCount + 1 );
6898 pSet->maString.clear();
6899 if ( nBehind )
6901 PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pSet );
6902 pNewCPS->maString = aString.copy( nCount + 1, nBehind );
6903 aCharPropList.emplace( aCharPropList.begin() + n + 1, pNewCPS );
6905 if ( (*FE)->xField2 )
6907 PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pSet );
6908 pNewCPS->mpFieldItem = std::move((*FE)->xField2);
6909 aCharPropList.emplace( aCharPropList.begin() + n + 1, pNewCPS );
6911 pNewCPS = new PPTCharPropSet( *pSet );
6912 pNewCPS->maString = " ";
6913 aCharPropList.emplace( aCharPropList.begin() + n + 1, pNewCPS );
6915 if ( nCount )
6917 PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pSet );
6918 pNewCPS->maString = aString.copy( 0, nCount );
6919 aCharPropList.emplace( aCharPropList.begin() + n++, pNewCPS );
6921 if ( (*FE)->xField1 )
6923 pSet->mpFieldItem = std::move((*FE)->xField1);
6925 else if ( (*FE)->xString )
6926 pSet->maString = *(*FE)->xString;
6928 else
6930 if ( (*FE)->nTextRangeEnd ) // text range hyperlink
6932 sal_uInt32 nHyperLen = (*FE)->nTextRangeEnd - nPos;
6933 if ( nHyperLen )
6935 PPTCharPropSet* pBefCPS = nullptr;
6936 if ( nCount )
6938 pBefCPS = new PPTCharPropSet( *pSet );
6939 pSet->maString = pSet->maString.copy(nCount);
6941 sal_uInt32 nIdx = n;
6942 sal_Int32 nHyperLenLeft = nHyperLen;
6944 while ( ( aCharPropList.size() > nIdx ) && nHyperLenLeft )
6946 // the textrange hyperlink can take more than 1 paragraph
6947 // the solution here is to clone the hyperlink...
6949 PPTCharPropSet* pCurrent = aCharPropList[ nIdx ].get();
6950 sal_Int32 nNextStringLen = pCurrent->maString.getLength();
6952 DBG_ASSERT( (*FE)->xField1, "missing field!" );
6953 if (!(*FE)->xField1)
6954 break;
6956 const SvxURLField* pField = static_cast<const SvxURLField*>((*FE)->xField1->GetField());
6958 pCurrent->mbIsHyperlink = true;
6959 pCurrent->mnHylinkOrigColor = pCurrent->mpImplPPTCharPropSet->mnColor;
6960 pCurrent->mbHardHylinkOrigColor = ( ( pCurrent->mpImplPPTCharPropSet->mnAttrSet >>PPT_CharAttr_FontColor ) & 1)>0;
6962 // add missing attribute to show underline property
6963 pCurrent->mpImplPPTCharPropSet->mnAttrSet |= 1 << PPT_CharAttr_Underline;
6964 pCurrent->mpImplPPTCharPropSet->mnFlags = 1 << PPT_CharAttr_Underline;
6966 if ( pCurrent->mpFieldItem )
6968 pCurrent->SetColor( PPT_COLSCHEME_A_UND_HYPERLINK );
6969 if ( dynamic_cast< const SvxURLField* >(pCurrent->mpFieldItem->GetField()) != nullptr)
6970 break;
6971 nHyperLenLeft--;
6973 else if ( nNextStringLen )
6975 if ( nNextStringLen <= nHyperLenLeft )
6977 pCurrent->mpFieldItem.reset( new SvxFieldItem( SvxURLField( pField->GetURL(), pCurrent->maString, SvxURLFormat::Repr ), EE_FEATURE_FIELD ) );
6978 nHyperLenLeft -= nNextStringLen;
6980 if ( nHyperLenLeft )
6982 // if the next portion is in a higher paragraph,
6983 // the textrange is to decrease (because of the LineBreak character)
6984 if ( aCharPropList.size() > ( nIdx + 1 ) )
6986 PPTCharPropSet* pNext = aCharPropList[ nIdx + 1 ].get();
6987 if ( pNext->mnParagraph > pCurrent->mnParagraph )
6988 nHyperLenLeft--;
6992 else
6994 PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pCurrent );
6995 pNewCPS->maString = pCurrent->maString.copy( nHyperLenLeft,( nNextStringLen - nHyperLenLeft ) );
6996 aCharPropList.emplace( aCharPropList.begin() + nIdx + 1, pNewCPS );
6997 OUString aRepresentation = pCurrent->maString.copy( 0, nHyperLenLeft );
6998 pCurrent->mpFieldItem.reset( new SvxFieldItem( SvxURLField( pField->GetURL(), aRepresentation, SvxURLFormat::Repr ), EE_FEATURE_FIELD ) );
6999 nHyperLenLeft = 0;
7001 pCurrent->maString.clear();
7002 pCurrent->SetColor( PPT_COLSCHEME_A_UND_HYPERLINK );
7004 nIdx++;
7006 (*FE)->xField1.reset();
7008 if ( pBefCPS )
7010 pBefCPS->maString = aString.copy( 0, nCount );
7011 aCharPropList.emplace( aCharPropList.begin() + n, pBefCPS );
7012 n++;
7017 break;
7020 n--;
7023 mxImplTextObj->maParagraphList.resize( nParagraphs );
7024 for (size_t nCurCharPos = 0, nCurPos = 0;
7025 nCurPos < aStyleTextPropReader.aParaPropList.size();
7026 ++nCurPos)
7028 mxImplTextObj->maParagraphList[ nCurPos ].reset(
7029 new PPTParagraphObj(
7030 aStyleTextPropReader, nCurPos, nCurCharPos,
7031 *rSdrPowerPointImport.m_pPPTStyleSheet,
7032 nInstance, aTextRulerInterpreter ) );
7034 sal_uInt32 nParaAdjust, nFlags = 0;
7035 mxImplTextObj->maParagraphList[ nCurPos ]->GetAttrib( PPT_ParaAttr_Adjust, nParaAdjust, GetInstance() );
7037 switch ( nParaAdjust )
7039 case 0 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT; break;
7040 case 1 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER; break;
7041 case 2 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT; break;
7042 case 3 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK; break;
7044 mxImplTextObj->mnTextFlags |= nFlags;
7048 PPTTextObj::PPTTextObj( PPTTextObj const & rTextObj )
7050 mxImplTextObj = rTextObj.mxImplTextObj;
7053 PPTTextObj::~PPTTextObj()
7057 PPTParagraphObj* PPTTextObj::First()
7059 mxImplTextObj->mnCurrentObject = 0;
7060 if ( !mxImplTextObj->mnParagraphCount )
7061 return nullptr;
7062 return mxImplTextObj->maParagraphList[ 0 ].get();
7065 PPTParagraphObj* PPTTextObj::Next()
7067 sal_uInt32 i = mxImplTextObj->mnCurrentObject + 1;
7068 if ( i >= mxImplTextObj->mnParagraphCount )
7069 return nullptr;
7070 mxImplTextObj->mnCurrentObject++;
7071 return mxImplTextObj->maParagraphList[ i ].get();
7074 const SfxItemSet* PPTTextObj::GetBackground() const
7076 if ( mxImplTextObj->mrPersistEntry.pBObj )
7077 return &mxImplTextObj->mrPersistEntry.pBObj->GetMergedItemSet();
7078 else
7079 return nullptr;
7082 PPTTextObj& PPTTextObj::operator=( const PPTTextObj& rTextObj )
7084 if ( this != &rTextObj )
7086 mxImplTextObj = rTextObj.mxImplTextObj;
7088 return *this;
7091 static bool IsLine( const SdrObject* pObj )
7093 auto pSdrPathObj = dynamic_cast< const SdrPathObj* >(pObj);
7094 return pSdrPathObj && pSdrPathObj->IsLine() && pSdrPathObj->GetPointCount() == 2;
7097 static bool GetCellPosition( const SdrObject* pObj, const o3tl::sorted_vector< sal_Int32 >& rRows, const o3tl::sorted_vector< sal_Int32 >& rColumns,
7098 sal_Int32& nTableIndex, sal_Int32& nRow, sal_Int32& nRowCount, sal_Int32& nColumn, sal_Int32& nColumnCount )
7100 tools::Rectangle aSnapRect( pObj->GetSnapRect() );
7101 bool bCellObject = ( aSnapRect.GetWidth() > 1 ) && ( aSnapRect.GetHeight() > 1 );
7102 if ( bCellObject )
7104 auto aRowIter = rRows.find( aSnapRect.Top() );
7105 auto aColumnIter = rColumns.find( aSnapRect.Left() );
7106 if ( ( aRowIter == rRows.end() ) || ( aColumnIter == rColumns.end() ) )
7107 bCellObject = false;
7108 else
7110 nRowCount = 1;
7111 nRow = std::distance( rRows.begin(), aRowIter );
7112 while( ++aRowIter != rRows.end() )
7114 if ( *aRowIter >= aSnapRect.Bottom() )
7115 break;
7116 nRowCount++;
7118 nColumnCount = 1;
7119 nColumn = std::distance( rColumns.begin(), aColumnIter );
7120 while( ++aColumnIter != rColumns.end() )
7122 if ( *aColumnIter >= aSnapRect.Right() )
7123 break;
7124 nColumnCount++;
7126 nTableIndex = nRow * rColumns.size() + nColumn;
7129 return bCellObject;
7132 #define LinePositionLeft 0x01000000
7133 #define LinePositionTop 0x02000000
7134 #define LinePositionRight 0x04000000
7135 #define LinePositionBottom 0x08000000
7136 #define LinePositionTLBR 0x10000000
7137 #define LinePositionBLTR 0x20000000
7140 static void GetRowPositions( const tools::Rectangle& rSnapRect, const o3tl::sorted_vector< sal_Int32 >& rRows,
7141 const o3tl::sorted_vector< sal_Int32 >& rColumns, std::vector< sal_Int32 >& rPositions, sal_Int32 nColumn, sal_Int32 nFlags )
7143 auto aRow = rRows.find( rSnapRect.Top() );
7144 if ( aRow == rRows.end() )
7145 return;
7147 sal_Int32 nRow = std::distance( rRows.begin(), aRow );
7148 while( ( aRow != rRows.end() ) && ((*aRow) < rSnapRect.Bottom() ) )
7150 if ( nFlags & LinePositionLeft )
7151 rPositions.push_back( ( ( nRow * rColumns.size() ) + nColumn ) | LinePositionLeft );
7152 if ( nFlags & LinePositionRight )
7153 rPositions.push_back( ( ( nRow * rColumns.size() ) + ( nColumn - 1 ) ) | LinePositionRight );
7155 ++nRow;
7156 ++aRow;
7161 static void GetColumnPositions( const tools::Rectangle& rSnapRect,
7162 const o3tl::sorted_vector< sal_Int32 >& rColumns, std::vector< sal_Int32 >& rPositions, sal_Int32 nRow, sal_Int32 nFlags )
7164 auto aColumn = rColumns.find( rSnapRect.Left() );
7165 if ( aColumn == rColumns.end() )
7166 return;
7168 sal_Int32 nColumn = std::distance( rColumns.begin(), aColumn );
7169 while( ( aColumn != rColumns.end() ) && ((*aColumn) < rSnapRect.Right() ) )
7171 if ( nFlags & LinePositionTop )
7172 rPositions.push_back( ( ( nRow * rColumns.size() ) + nColumn ) | LinePositionTop );
7173 if ( nFlags & LinePositionBottom )
7174 rPositions.push_back( ( ( ( nRow - 1 ) * rColumns.size() ) + nColumn ) | LinePositionBottom );
7176 ++nColumn;
7177 ++aColumn;
7181 static void GetLinePositions( const SdrObject* pObj, const o3tl::sorted_vector< sal_Int32 >& rRows, const o3tl::sorted_vector< sal_Int32 >& rColumns,
7182 std::vector< sal_Int32 >& rPositions, const tools::Rectangle& rGroupSnap )
7184 tools::Rectangle aSnapRect( pObj->GetSnapRect() );
7185 if ( aSnapRect.Left() == aSnapRect.Right() )
7187 auto aColumn = rColumns.find( aSnapRect.Left() );
7188 if ( ( aColumn != rColumns.end() ) || ( aSnapRect.Left() == rGroupSnap.Right() ) )
7190 sal_Int32 nColumn, nFlags;
7191 if ( aColumn != rColumns.end() )
7193 nColumn = std::distance( rColumns.begin(), aColumn );
7194 nFlags = LinePositionLeft;
7195 if ( aColumn != rColumns.begin() )
7196 nFlags |= LinePositionRight;
7198 else
7200 nColumn = rColumns.size();
7201 nFlags = LinePositionRight;
7203 GetRowPositions( aSnapRect, rRows, rColumns, rPositions, nColumn, nFlags );
7206 else if ( aSnapRect.Top() == aSnapRect.Bottom() )
7208 auto aRow = rRows.find( aSnapRect.Top() );
7209 if ( ( aRow != rRows.end() ) || ( aSnapRect.Top() == rGroupSnap.Bottom() ) )
7211 sal_Int32 nRow, nFlags;
7212 if ( aRow != rRows.end() )
7214 nRow = std::distance( rRows.begin(), aRow );
7215 nFlags = LinePositionTop;
7216 if ( aRow != rRows.begin() )
7217 nFlags |= LinePositionBottom;
7219 else
7221 nRow = rRows.size();
7222 nFlags = LinePositionBottom;
7224 GetColumnPositions( aSnapRect, rColumns, rPositions, nRow, nFlags );
7227 else
7229 sal_uInt32 nPosition = 0;
7230 Point aPt1( static_cast<const SdrPathObj*>(pObj)->GetPoint( 0 ) );
7231 Point aPt2( static_cast<const SdrPathObj*>(pObj)->GetPoint( 1 ) );
7232 if ( aPt1.X() < aPt2.X() )
7233 nPosition |= aPt1.Y() < aPt2.Y() ? LinePositionTLBR : LinePositionBLTR;
7234 else
7235 nPosition |= aPt1.Y() < aPt2.Y() ? LinePositionBLTR : LinePositionTLBR;
7237 auto aRow = rRows.find( std::min(aPt1.Y(), aPt2.Y() ) );
7238 auto aColumn = rColumns.find( std::min(aPt1.X(), aPt2.X() ) );
7239 if ( ( aRow != rRows.end() ) && ( aColumn != rColumns.end() ) )
7241 nPosition |= ( std::distance( rRows.begin(), aRow ) * rColumns.size() ) + std::distance( rColumns.begin(), aColumn );
7242 rPositions.push_back( nPosition );
7247 static void CreateTableRows( const Reference< XTableRows >& xTableRows, const o3tl::sorted_vector< sal_Int32 >& rRows, sal_Int32 nTableBottom )
7249 if ( rRows.size() > 1 )
7250 xTableRows->insertByIndex( 0, rRows.size() - 1 );
7252 auto aIter = rRows.begin();
7253 sal_Int32 nLastPosition( *aIter );
7254 for ( sal_Int32 n = 0; n < xTableRows->getCount(); n++ )
7256 sal_Int32 nHeight;
7257 if ( ++aIter != rRows.end() )
7259 if (o3tl::checked_sub<sal_Int32>(*aIter, nLastPosition, nHeight))
7260 throw lang::IllegalArgumentException();
7261 nLastPosition = *aIter;
7263 else
7265 if (o3tl::checked_sub<sal_Int32>(nTableBottom, nLastPosition, nHeight))
7266 throw lang::IllegalArgumentException();
7269 Reference< XPropertySet > xPropSet( xTableRows->getByIndex( n ), UNO_QUERY_THROW );
7270 xPropSet->setPropertyValue( "Height", Any( nHeight ) );
7274 static void CreateTableColumns( const Reference< XTableColumns >& xTableColumns, const o3tl::sorted_vector< sal_Int32 >& rColumns, sal_Int32 nTableRight )
7276 if ( rColumns.size() > 1 )
7277 xTableColumns->insertByIndex( 0, rColumns.size() - 1 );
7279 auto aIter = rColumns.begin();
7280 sal_Int32 nLastPosition( *aIter );
7281 for ( sal_Int32 n = 0; n < xTableColumns->getCount(); n++ )
7283 sal_Int32 nWidth;
7284 if ( ++aIter != rColumns.end() )
7286 if (o3tl::checked_sub<sal_Int32>(*aIter, nLastPosition, nWidth))
7287 throw lang::IllegalArgumentException();
7288 nLastPosition = *aIter;
7290 else
7292 if (o3tl::checked_sub<sal_Int32>(nTableRight, nLastPosition, nWidth))
7293 throw lang::IllegalArgumentException();
7296 Reference< XPropertySet > xPropSet( xTableColumns->getByIndex( n ), UNO_QUERY_THROW );
7297 xPropSet->setPropertyValue( "Width", Any( nWidth ) );
7301 static void MergeCells( const Reference< XTable >& xTable, sal_Int32 nCol, sal_Int32 nRow, sal_Int32 nColSpan, sal_Int32 nRowSpan )
7303 DBG_ASSERT( (nColSpan > 1) || (nRowSpan > 1), "nonsense parameter!!" );
7304 DBG_ASSERT( (nCol >= 0) && (nCol < xTable->getColumnCount()) && (nRow >= 0) && (nRow < xTable->getRowCount()), "the cell does not exists!!" );
7305 DBG_ASSERT( (nColSpan >= 1) && ((nCol + nColSpan - 1) < xTable->getColumnCount()), "nColSpan botch!" );
7306 DBG_ASSERT( (nRowSpan >= 1) && ((nRow + nRowSpan - 1) < xTable->getRowCount()), "nRowSpan botch!" );
7308 if( xTable.is() ) try
7310 Reference< XMergeableCellRange > xRange( xTable->createCursorByRange( xTable->getCellRangeByPosition( nCol, nRow,nCol + nColSpan - 1, nRow + nRowSpan - 1 ) ), UNO_QUERY_THROW );
7311 if( xRange->isMergeable() )
7312 xRange->merge();
7314 catch( const Exception& )
7316 DBG_UNHANDLED_EXCEPTION("filter.ms");
7320 static void ApplyCellAttributes( const SdrObject* pObj, Reference< XCell > const & xCell )
7324 Reference< XPropertySet > xPropSet( xCell, UNO_QUERY_THROW );
7326 const sal_Int32 nLeftDist(pObj->GetMergedItem(SDRATTR_TEXT_LEFTDIST).GetValue());
7327 const sal_Int32 nRightDist(pObj->GetMergedItem(SDRATTR_TEXT_RIGHTDIST).GetValue());
7328 const sal_Int32 nUpperDist(pObj->GetMergedItem(SDRATTR_TEXT_UPPERDIST).GetValue());
7329 const sal_Int32 nLowerDist(pObj->GetMergedItem(SDRATTR_TEXT_LOWERDIST).GetValue());
7330 xPropSet->setPropertyValue( "TextUpperDistance", Any( nUpperDist ) );
7331 xPropSet->setPropertyValue( "TextRightDistance", Any( nRightDist ) );
7332 xPropSet->setPropertyValue( "TextLeftDistance", Any( nLeftDist ) );
7333 xPropSet->setPropertyValue( "TextLowerDistance", Any( nLowerDist ) );
7335 const SdrTextVertAdjust eTextVertAdjust(pObj->GetMergedItem(SDRATTR_TEXT_VERTADJUST).GetValue());
7336 drawing::TextVerticalAdjust eVA( drawing::TextVerticalAdjust_TOP );
7337 if ( eTextVertAdjust == SDRTEXTVERTADJUST_CENTER )
7338 eVA = drawing::TextVerticalAdjust_CENTER;
7339 else if ( eTextVertAdjust == SDRTEXTVERTADJUST_BOTTOM )
7340 eVA = drawing::TextVerticalAdjust_BOTTOM;
7341 xPropSet->setPropertyValue( "TextVerticalAdjust", Any( eVA ) );
7343 //set textHorizontalAdjust and TextWritingMode attr
7344 const sal_Int32 eHA(pObj->GetMergedItem(SDRATTR_TEXT_HORZADJUST).GetValue());
7345 const SvxFrameDirection eDirection = pObj->GetMergedItem(EE_PARA_WRITINGDIR).GetValue();
7346 xPropSet->setPropertyValue( "TextHorizontalAdjust" , Any( eHA ) );
7347 if ( eDirection == SvxFrameDirection::Vertical_RL_TB )
7348 {//vertical writing
7349 xPropSet->setPropertyValue( "TextWritingMode" , Any( css::text::WritingMode_TB_RL ) );
7351 drawing::FillStyle eFillStyle(pObj->GetMergedItem( XATTR_FILLSTYLE ).GetValue());
7352 css::drawing::FillStyle eFS( css::drawing::FillStyle_NONE );
7353 switch( eFillStyle )
7355 case drawing::FillStyle_SOLID :
7357 eFS = css::drawing::FillStyle_SOLID;
7358 Color aFillColor( pObj->GetMergedItem( XATTR_FILLCOLOR ).GetColorValue() );
7359 xPropSet->setPropertyValue( "FillColor", Any( aFillColor ) );
7361 break;
7362 case drawing::FillStyle_GRADIENT :
7364 eFS = css::drawing::FillStyle_GRADIENT;
7365 basegfx::BGradient aBGradient(pObj->GetMergedItem(XATTR_FILLGRADIENT).GetGradientValue());
7367 css::awt::Gradient aGradient;
7368 aGradient.Style = aBGradient.GetGradientStyle();
7369 aGradient.StartColor = static_cast<sal_Int32>(Color(aBGradient.GetColorStops().front().getStopColor()));
7370 aGradient.EndColor = static_cast<sal_Int32>(Color(aBGradient.GetColorStops().back().getStopColor()));
7371 aGradient.Angle = static_cast<short>(aBGradient.GetAngle());
7372 aGradient.Border = aBGradient.GetBorder();
7373 aGradient.XOffset = aBGradient.GetXOffset();
7374 aGradient.YOffset = aBGradient.GetYOffset();
7375 aGradient.StartIntensity = aBGradient.GetStartIntens();
7376 aGradient.EndIntensity = aBGradient.GetEndIntens();
7377 aGradient.StepCount = aBGradient.GetSteps();
7379 xPropSet->setPropertyValue( "FillGradient", Any( aGradient ) );
7381 break;
7382 case drawing::FillStyle_HATCH :
7383 eFS = css::drawing::FillStyle_HATCH;
7384 break;
7385 case drawing::FillStyle_BITMAP :
7387 eFS = css::drawing::FillStyle_BITMAP;
7389 const XFillBitmapItem & rXFillBitmapItem(pObj->GetMergedItem( XATTR_FILLBITMAP ));
7390 uno::Reference<graphic::XGraphic> xGraphic = rXFillBitmapItem.GetGraphicObject().GetGraphic().GetXGraphic();
7391 uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
7392 xPropSet->setPropertyValue("FillBitmap", uno::Any(xBitmap));
7394 const XFillBmpStretchItem & rStretchItem(pObj->GetMergedItem( XATTR_FILLBMP_STRETCH ));
7395 const XFillBmpTileItem & rTileItem(pObj->GetMergedItem( XATTR_FILLBMP_TILE ));
7396 if( rTileItem.GetValue() )
7397 xPropSet->setPropertyValue("FillBitmapMode", uno::Any(drawing::BitmapMode_REPEAT));
7398 else if( rStretchItem.GetValue() )
7399 xPropSet->setPropertyValue("FillBitmapMode", uno::Any(drawing::BitmapMode_STRETCH));
7400 else
7401 xPropSet->setPropertyValue("FillBitmapMode", uno::Any(drawing::BitmapMode_NO_REPEAT));
7403 break;
7404 default:
7405 case drawing::FillStyle_NONE :
7406 eFS = css::drawing::FillStyle_NONE;
7407 break;
7410 xPropSet->setPropertyValue( "FillStyle", Any( eFS ) );
7411 if ( eFillStyle != drawing::FillStyle_NONE )
7413 sal_Int16 nFillTransparence( pObj->GetMergedItem( XATTR_FILLTRANSPARENCE ).GetValue() );
7414 xPropSet->setPropertyValue( "FillTransparence", Any( nFillTransparence ) );
7417 catch( const Exception& )
7422 static void ApplyCellLineAttributes( const SdrObject* pLine, Reference< XTable > const & xTable, const std::vector< sal_Int32 >& vPositions, sal_Int32 nColumns )
7426 drawing::LineStyle eLineStyle(pLine->GetMergedItem( XATTR_LINESTYLE ).GetValue());
7427 css::table::BorderLine2 aBorderLine;
7428 switch( eLineStyle )
7430 case drawing::LineStyle_DASH :
7431 case drawing::LineStyle_SOLID :
7433 Color aLineColor( pLine->GetMergedItem( XATTR_LINECOLOR ).GetColorValue() );
7434 aBorderLine.Color = sal_Int32(aLineColor);
7435 // Avoid width = 0, the min value should be 1.
7436 sal_Int32 nLineWidth = std::max(sal_Int32(1), pLine->GetMergedItem(XATTR_LINEWIDTH) .GetValue() / 4);
7437 aBorderLine.LineWidth = static_cast< sal_Int16 >( nLineWidth );
7438 aBorderLine.LineStyle = eLineStyle == drawing::LineStyle_SOLID ? table::BorderLineStyle::SOLID : table::BorderLineStyle::DASHED;
7440 break;
7441 default:
7442 case drawing::LineStyle_NONE :
7444 aBorderLine.LineWidth = 0;
7445 aBorderLine.LineStyle = table::BorderLineStyle::NONE;
7447 break;
7449 for (auto const& vPos : vPositions)
7451 sal_Int32 nPosition = vPos & 0xffffff;
7452 sal_Int32 nFlags = vPos &~0xffffff;
7453 sal_Int32 nRow = nPosition / nColumns;
7454 sal_Int32 nColumn = nPosition - ( nRow * nColumns );
7455 Reference< XCell > xCell( xTable->getCellByPosition( nColumn, nRow ) );
7456 Reference< XPropertySet > xPropSet( xCell, UNO_QUERY_THROW );
7458 if ( nFlags & LinePositionLeft )
7459 xPropSet->setPropertyValue( "LeftBorder", Any( aBorderLine ) );
7460 if ( nFlags & LinePositionTop )
7461 xPropSet->setPropertyValue( "TopBorder", Any( aBorderLine ) );
7462 if ( nFlags & LinePositionRight )
7463 xPropSet->setPropertyValue( "RightBorder", Any( aBorderLine ) );
7464 if ( nFlags & LinePositionBottom )
7465 xPropSet->setPropertyValue( "BottomBorder", Any( aBorderLine ) );
7466 if ( nFlags & LinePositionTLBR )
7467 xPropSet->setPropertyValue( "DiagonalTLBR", Any( true ) );
7468 if ( nFlags & LinePositionBLTR )
7469 xPropSet->setPropertyValue( "DiagonalBLTR", Any( true ) );
7472 catch( const Exception& )
7477 rtl::Reference<SdrObject> SdrPowerPointImport::CreateTable(
7478 SdrObject* pGroup, const sal_uInt32* pTableArry,
7479 SvxMSDffSolverContainer* pSolverContainer)
7481 rtl::Reference<SdrObject> pRet = pGroup;
7483 sal_uInt32 nRows = pTableArry[ 1 ];
7484 if (!nRows)
7485 return pRet;
7487 const SdrObjGroup* pObjGroup = dynamic_cast<const SdrObjGroup*>(pGroup);
7488 if (!pObjGroup)
7489 return pRet;
7491 SdrObjList* pSubList(pObjGroup->GetSubList());
7492 if (!pSubList)
7493 return pRet;
7495 o3tl::sorted_vector< sal_Int32 > aRows;
7496 o3tl::sorted_vector< sal_Int32 > aColumns;
7498 SdrObjListIter aGroupIter( pSubList, SdrIterMode::DeepNoGroups, false );
7499 while( aGroupIter.IsMore() )
7501 const SdrObject* pObj( aGroupIter.Next() );
7502 if ( !IsLine( pObj ) )
7504 tools::Rectangle aSnapRect( pObj->GetSnapRect() );
7505 aRows.insert( aSnapRect.Top() );
7506 aColumns.insert( aSnapRect.Left() );
7510 if (aRows.empty())
7511 return pRet;
7513 rtl::Reference<sdr::table::SdrTableObj> pTable = new sdr::table::SdrTableObj(*pSdrModel);
7514 pTable->uno_lock();
7515 Reference< XTable > xTable( pTable->getTable() );
7519 CreateTableRows( xTable->getRows(), aRows, pGroup->GetSnapRect().Bottom() );
7520 CreateTableColumns( xTable->getColumns(), aColumns, pGroup->GetSnapRect().Right() );
7522 sal_Int32 nCellCount = aRows.size() * aColumns.size();
7523 std::unique_ptr<sal_Int32[]> pMergedCellIndexTable(new sal_Int32[ nCellCount ]);
7524 for ( sal_Int32 i = 0; i < nCellCount; i++ )
7525 pMergedCellIndexTable[ i ] = i;
7527 aGroupIter.Reset();
7528 while( aGroupIter.IsMore() )
7530 SdrObject* pObj( aGroupIter.Next() );
7531 if ( !IsLine( pObj ) )
7533 sal_Int32 nTableIndex = 0;
7534 sal_Int32 nRow = 0;
7535 sal_Int32 nRowCount = 0;
7536 sal_Int32 nColumn = 0;
7537 sal_Int32 nColumnCount = 0;
7538 if ( GetCellPosition( pObj, aRows, aColumns, nTableIndex, nRow, nRowCount, nColumn, nColumnCount ) )
7540 Reference< XCell > xCell( xTable->getCellByPosition( nColumn, nRow ) );
7542 ApplyCellAttributes( pObj, xCell );
7544 if ( ( nRowCount > 1 ) || ( nColumnCount > 1 ) ) // cell merging
7546 MergeCells( xTable, nColumn, nRow, nColumnCount, nRowCount );
7547 for ( sal_Int32 nRowIter = 0; nRowIter < nRowCount; nRowIter++ )
7549 for ( sal_Int32 nColumnIter = 0; nColumnIter < nColumnCount; nColumnIter++ )
7550 { // now set the correct index for the merged cell
7551 pMergedCellIndexTable[ ( ( nRow + nRowIter ) * aColumns.size() ) + nColumn + nColumnIter ] = nTableIndex;
7556 // applying text
7557 OutlinerParaObject* pParaObject = pObj->GetOutlinerParaObject();
7558 if ( pParaObject )
7560 SdrText* pSdrText = pTable->getText( nTableIndex );
7561 if ( pSdrText )
7562 pSdrText->SetOutlinerParaObject(*pParaObject);
7567 aGroupIter.Reset();
7568 while( aGroupIter.IsMore() )
7570 SdrObject* pObj( aGroupIter.Next() );
7571 if ( IsLine( pObj ) )
7573 std::vector< sal_Int32 > vPositions; // containing cell indexes + cell position
7574 GetLinePositions( pObj, aRows, aColumns, vPositions, pGroup->GetSnapRect() );
7576 // correcting merged cell position
7577 for (auto & vPos : vPositions)
7579 sal_Int32 nOldPosition = vPos & 0xffff;
7580 sal_Int32 nOldFlags = vPos & 0xffff0000;
7581 sal_Int32 nNewPosition = pMergedCellIndexTable[ nOldPosition ] | nOldFlags;
7582 vPos = nNewPosition;
7584 ApplyCellLineAttributes( pObj, xTable, vPositions, aColumns.size() );
7587 pMergedCellIndexTable.reset();
7589 // we are replacing the whole group object by a single table object, so
7590 // possibly connections to the group object have to be removed.
7591 if ( pSolverContainer )
7593 for (auto & pPtr : pSolverContainer->aCList)
7595 // check connections to the group object
7596 if ( pPtr->pAObj == pGroup )
7597 pPtr->pAObj = nullptr;
7598 if ( pPtr->pBObj == pGroup )
7599 pPtr->pBObj = nullptr;
7601 // check connections to all its subobjects
7602 SdrObjListIter aIter( *pGroup, SdrIterMode::DeepWithGroups );
7603 while( aIter.IsMore() )
7605 SdrObject* pPartObj = aIter.Next();
7606 if ( pPtr->pAObj == pPartObj )
7607 pPtr->pAObj = nullptr;
7608 if ( pPtr->pBObj == pPartObj )
7609 pPtr->pBObj = nullptr;
7611 //In MS, the one_row_one_col table is made up of five
7612 //shape,the connector is connected to some part of a
7613 //table. But for us, the connector is connected to the
7614 //whole group table,so the connector obj is a group
7615 //table when export by us. We should process this
7616 //situation when importing.
7617 if ( pPtr->pAObj == pGroup )
7618 pPtr->pAObj = pTable.get();
7619 if ( pPtr->pBObj == pGroup )
7620 pPtr->pBObj = pTable.get();
7623 pTable->uno_unlock();
7624 pTable->SetSnapRect( pGroup->GetSnapRect() );
7625 pRet = pTable;
7627 //Remove Objects from shape map
7628 SdrObjListIter aIter( *pGroup, SdrIterMode::DeepWithGroups );
7629 while( aIter.IsMore() )
7631 SdrObject* pPartObj = aIter.Next();
7632 removeShapeId(pPartObj);
7635 catch( const Exception& )
7637 pTable->uno_unlock();
7638 pTable = nullptr;
7641 return pRet;
7644 bool SdrPowerPointImport::IsVerticalText() const
7646 bool bVerticalText = false;
7647 if ( IsProperty( DFF_Prop_txflTextFlow ) )
7649 auto eTextFlow = GetPropertyValue(DFF_Prop_txflTextFlow, 0) & 0xFFFF;
7650 switch( eTextFlow )
7652 case mso_txflTtoBA : // Top to Bottom @-font, above -> below
7653 case mso_txflTtoBN : // Top to Bottom non-@, above -> below
7654 case mso_txflVertN : // Vertical, non-@, above -> below
7655 bVerticalText = !bVerticalText;
7656 break;
7657 default: break;
7661 return bVerticalText;
7664 void SdrPowerPointImport::ApplyTextAnchorAttributes( PPTTextObj const & rTextObj, SfxItemSet& rSet ) const
7666 SdrTextVertAdjust eTVA;
7667 SdrTextHorzAdjust eTHA;
7669 sal_uInt32 nTextFlags = rTextObj.GetTextFlags();
7671 nTextFlags &= PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT
7672 | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK;
7674 if ( IsVerticalText() )
7676 eTVA = SDRTEXTVERTADJUST_BLOCK;
7677 eTHA = SDRTEXTHORZADJUST_CENTER;
7679 // read text anchor
7680 auto eTextAnchor = GetPropertyValue(DFF_Prop_anchorText, mso_anchorTop);
7682 switch( eTextAnchor )
7684 case mso_anchorTop:
7685 case mso_anchorTopCentered:
7686 eTHA = SDRTEXTHORZADJUST_RIGHT;
7687 break;
7689 case mso_anchorMiddle :
7690 case mso_anchorMiddleCentered:
7691 eTHA = SDRTEXTHORZADJUST_CENTER;
7692 break;
7694 case mso_anchorBottom:
7695 case mso_anchorBottomCentered:
7696 eTHA = SDRTEXTHORZADJUST_LEFT;
7697 break;
7699 default:
7700 break;
7702 // if there is a 100% use of following attributes, the textbox can been aligned also in vertical direction
7703 switch ( eTextAnchor )
7705 case mso_anchorTopCentered :
7706 case mso_anchorMiddleCentered :
7707 case mso_anchorBottomCentered :
7709 // check if it is sensible to use the centered alignment
7710 sal_uInt32 nMask = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT;
7711 if ( ( nTextFlags & nMask ) != nMask ) // if the textobject has left or also right aligned paragraphs
7712 eTVA = SDRTEXTVERTADJUST_CENTER; // the text has to be displayed using the full width;
7714 break;
7716 default :
7718 if ( nTextFlags == PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT )
7719 eTVA = SDRTEXTVERTADJUST_TOP;
7720 else if ( nTextFlags == PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT )
7721 eTVA = SDRTEXTVERTADJUST_BOTTOM;
7723 break;
7726 else
7728 eTVA = SDRTEXTVERTADJUST_CENTER;
7729 eTHA = SDRTEXTHORZADJUST_BLOCK;
7731 // read text anchor
7732 auto eTextAnchor = GetPropertyValue(DFF_Prop_anchorText, mso_anchorTop);
7734 switch( eTextAnchor )
7736 case mso_anchorTop:
7737 case mso_anchorTopCentered:
7738 eTVA = SDRTEXTVERTADJUST_TOP;
7739 break;
7741 case mso_anchorMiddle :
7742 case mso_anchorMiddleCentered:
7743 eTVA = SDRTEXTVERTADJUST_CENTER;
7744 break;
7746 case mso_anchorBottom:
7747 case mso_anchorBottomCentered:
7748 eTVA = SDRTEXTVERTADJUST_BOTTOM;
7749 break;
7751 default:
7752 break;
7755 // if there is a 100% usage of following attributes, the textbox can be aligned also in horizontal direction
7756 switch ( eTextAnchor )
7758 case mso_anchorTopCentered :
7759 case mso_anchorMiddleCentered :
7760 case mso_anchorBottomCentered :
7762 // check if it is sensible to use the centered alignment
7763 sal_uInt32 nMask = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT;
7764 if ( ( nTextFlags & nMask ) != nMask ) // if the textobject has left or also right aligned paragraphs
7765 eTHA = SDRTEXTHORZADJUST_CENTER; // the text has to be displayed using the full width;
7767 break;
7769 default :
7771 if ( nTextFlags == PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT )
7772 eTHA = SDRTEXTHORZADJUST_LEFT;
7773 else if ( nTextFlags == PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT )
7774 eTHA = SDRTEXTHORZADJUST_RIGHT;
7776 break;
7779 rSet.Put( SdrTextVertAdjustItem( eTVA ) );
7780 rSet.Put( SdrTextHorzAdjustItem( eTHA ) );
7783 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */