bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sd / source / filter / eppt / pptx-text.cxx
blob3b858a6dc556c8ff718b7cc46a0b8b15186fd727
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 <memory>
21 #include "text.hxx"
23 #include <com/sun/star/awt/CharSet.hpp>
24 #include <com/sun/star/awt/FontWeight.hpp>
25 #include <com/sun/star/awt/FontUnderline.hpp>
26 #include <com/sun/star/awt/XBitmap.hpp>
27 #include <com/sun/star/beans/XPropertyState.hpp>
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <com/sun/star/container/XEnumerationAccess.hpp>
30 #include <com/sun/star/container/XIndexReplace.hpp>
31 #include <com/sun/star/i18n/BreakIterator.hpp>
32 #include <com/sun/star/i18n/ScriptDirection.hpp>
33 #include <com/sun/star/i18n/ScriptType.hpp>
34 #include <com/sun/star/text/FontRelief.hpp>
35 #include <com/sun/star/text/XTextField.hpp>
36 #include <com/sun/star/text/XTextRange.hpp>
37 #include <com/sun/star/style/LineSpacing.hpp>
38 #include <com/sun/star/style/LineSpacingMode.hpp>
39 #include <com/sun/star/style/ParagraphAdjust.hpp>
40 #include <com/sun/star/style/TabStop.hpp>
41 #include <com/sun/star/graphic/XGraphic.hpp>
43 #include <comphelper/processfactory.hxx>
44 #include <editeng/svxenum.hxx>
45 #include <editeng/frmdir.hxx>
46 #include <filter/msfilter/util.hxx>
47 #include <i18nutil/scripttypedetector.hxx>
48 #include <o3tl/any.hxx>
49 #include <svl/languageoptions.hxx>
50 #include <osl/diagnose.h>
51 #include <i18nlangtag/languagetag.hxx>
53 #include <vcl/settings.hxx>
54 #include <vcl/metric.hxx>
55 #include <vcl/virdev.hxx>
56 #include <vcl/svapp.hxx>
58 using namespace css;
60 static css::uno::Reference< css::i18n::XBreakIterator > xPPTBreakIter;
62 PortionObj::PortionObj(const css::uno::Reference< css::beans::XPropertySet > & rXPropSet,
63 FontCollection& rFontCollection)
64 : meCharColor(css::beans::PropertyState_AMBIGUOUS_VALUE)
65 , meCharHeight(css::beans::PropertyState_AMBIGUOUS_VALUE)
66 , meFontName(css::beans::PropertyState_AMBIGUOUS_VALUE)
67 , meAsianOrComplexFont(css::beans::PropertyState_AMBIGUOUS_VALUE)
68 , meCharEscapement(css::beans::PropertyState_AMBIGUOUS_VALUE)
69 , mnCharAttrHard(0)
70 , mnCharAttr(0)
71 , mnFont(0)
72 , mnAsianOrComplexFont(0xffff)
73 , mnTextSize(0)
74 , mbLastPortion(true)
76 mXPropSet = rXPropSet;
78 ImplGetPortionValues( rFontCollection, false );
81 PortionObj::PortionObj(css::uno::Reference< css::text::XTextRange > & rXTextRange,
82 bool bLast, FontCollection& rFontCollection)
83 : meCharColor(css::beans::PropertyState_AMBIGUOUS_VALUE)
84 , meCharHeight(css::beans::PropertyState_AMBIGUOUS_VALUE)
85 , meFontName(css::beans::PropertyState_AMBIGUOUS_VALUE)
86 , meAsianOrComplexFont(css::beans::PropertyState_AMBIGUOUS_VALUE)
87 , meCharEscapement(css::beans::PropertyState_AMBIGUOUS_VALUE)
88 , mnCharAttrHard(0)
89 , mnCharColor(0)
90 , mnCharAttr(0)
91 , mnCharHeight(0)
92 , mnFont(0)
93 , mnAsianOrComplexFont(0xffff)
94 , mnCharEscapement(0)
95 , mbLastPortion(bLast)
97 OUString aString( rXTextRange->getString() );
98 OUString aURL;
100 mnTextSize = aString.getLength();
101 if ( bLast )
102 mnTextSize++;
104 if ( !mnTextSize )
105 return;
107 bool bRTL_endingParen = false;
108 mpFieldEntry = nullptr;
109 sal_uInt32 nFieldType = 0;
111 mXPropSet.set( rXTextRange, css::uno::UNO_QUERY );
112 mXPropState.set( rXTextRange, css::uno::UNO_QUERY );
114 bool bPropSetsValid = ( mXPropSet.is() && mXPropState.is() );
115 if ( bPropSetsValid )
116 nFieldType = ImplGetTextField( rXTextRange, mXPropSet, aURL );
117 if ( nFieldType )
119 mpFieldEntry.reset( new FieldEntry( nFieldType, 0, mnTextSize ) );
120 if ( nFieldType >> 28 == 4 )
122 mpFieldEntry->aRepresentation = aString;
123 mpFieldEntry->aFieldUrl = aURL;
126 bool bSymbol = false;
128 if ( bPropSetsValid && ImplGetPropertyValue( "CharFontCharSet", false ) )
130 sal_Int16 nCharset = 0;
131 mAny >>= nCharset;
132 if ( nCharset == css::awt::CharSet::SYMBOL )
133 bSymbol = true;
135 if ( mpFieldEntry && ( nFieldType & 0x800000 ) ) // placeholder ?
137 mnTextSize = 1;
138 if ( bLast )
139 mnTextSize++;
140 mpText.reset( new sal_uInt16[ mnTextSize ] );
141 mpText[ 0 ] = 0x2a;
143 else
145 // For i39516 - a closing parenthesis that ends an RTL string is displayed backwards by PPT
146 // Solution: add a Unicode Right-to-Left Mark, following the method described in i18024
147 if (bLast && !aString.isEmpty()
148 && aString[aString.getLength() - 1] == ')'
149 && FontCollection::GetScriptDirection(aString) == css::i18n::ScriptDirection::RIGHT_TO_LEFT)
151 mnTextSize++;
152 bRTL_endingParen = true;
154 mpText.reset( new sal_uInt16[ mnTextSize ] );
155 sal_uInt16 nChar;
156 for ( sal_Int32 i = 0; i < aString.getLength(); i++ )
158 nChar = static_cast<sal_uInt16>(aString[ i ]);
159 if ( nChar == 0xa )
160 nChar++;
161 else if ( !bSymbol )
163 switch ( nChar )
165 // Currency
166 case 128: nChar = 0x20AC; break;
167 // Punctuation and other
168 case 130: nChar = 0x201A; break;// SINGLE LOW-9 QUOTATION MARK
169 case 131: nChar = 0x0192; break;// LATIN SMALL LETTER F WITH HOOK
170 case 132: nChar = 0x201E; break;// DOUBLE LOW-9 QUOTATION MARK
171 // LOW DOUBLE PRIME QUOTATION MARK
172 case 133: nChar = 0x2026; break;// HORIZONTAL ELLIPSES
173 case 134: nChar = 0x2020; break;// DAGGER
174 case 135: nChar = 0x2021; break;// DOUBLE DAGGER
175 case 136: nChar = 0x02C6; break;// MODIFIER LETTER CIRCUMFLEX ACCENT
176 case 137: nChar = 0x2030; break;// PER MILLE SIGN
177 case 138: nChar = 0x0160; break;// LATIN CAPITAL LETTER S WITH CARON
178 case 139: nChar = 0x2039; break;// SINGLE LEFT-POINTING ANGLE QUOTATION MARK
179 case 140: nChar = 0x0152; break;// LATIN CAPITAL LIGATURE OE
180 case 142: nChar = 0x017D; break;// LATIN CAPITAL LETTER Z WITH CARON
181 case 145: nChar = 0x2018; break;// LEFT SINGLE QUOTATION MARK
182 // MODIFIER LETTER TURNED COMMA
183 case 146: nChar = 0x2019; break;// RIGHT SINGLE QUOTATION MARK
184 // MODIFIER LETTER APOSTROPHE
185 case 147: nChar = 0x201C; break;// LEFT DOUBLE QUOTATION MARK
186 // REVERSED DOUBLE PRIME QUOTATION MARK
187 case 148: nChar = 0x201D; break;// RIGHT DOUBLE QUOTATION MARK
188 // REVERSED DOUBLE PRIME QUOTATION MARK
189 case 149: nChar = 0x2022; break;// BULLET
190 case 150: nChar = 0x2013; break;// EN DASH
191 case 151: nChar = 0x2014; break;// EM DASH
192 case 152: nChar = 0x02DC; break;// SMALL TILDE
193 case 153: nChar = 0x2122; break;// TRADE MARK SIGN
194 case 154: nChar = 0x0161; break;// LATIN SMALL LETTER S WITH CARON
195 case 155: nChar = 0x203A; break;// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
196 case 156: nChar = 0x0153; break;// LATIN SMALL LIGATURE OE
197 case 158: nChar = 0x017E; break;// LATIN SMALL LETTER Z WITH CARON
198 case 159: nChar = 0x0178; break;// LATIN CAPITAL LETTER Y WITH DIAERESIS
201 mpText[ i ] = nChar;
204 if ( bRTL_endingParen )
205 mpText[ mnTextSize - 2 ] = 0x200F; // Unicode Right-to-Left mark
207 if ( bLast )
208 mpText[ mnTextSize - 1 ] = 0xd;
210 if ( bPropSetsValid )
211 ImplGetPortionValues( rFontCollection, true );
214 PortionObj::PortionObj( const PortionObj& rPortionObj )
215 : PropStateValue( rPortionObj )
217 ImplConstruct( rPortionObj );
220 PortionObj::~PortionObj()
222 ImplClear();
225 void PortionObj::Write( SvStream* pStrm, bool bLast )
227 sal_uInt32 nCount = mnTextSize;
228 if ( bLast && mbLastPortion )
229 nCount--;
230 for ( sal_uInt32 i = 0; i < nCount; i++ )
231 pStrm->WriteUInt16( mpText[ i ] );
234 void PortionObj::ImplGetPortionValues( FontCollection& rFontCollection, bool bGetPropStateValue )
237 bool bOk = ImplGetPropertyValue( "CharFontName", bGetPropStateValue );
238 meFontName = ePropState;
239 if ( bOk )
241 FontCollectionEntry aFontDesc( *o3tl::doAccess<OUString>(mAny) );
242 sal_uInt32 nCount = rFontCollection.GetCount();
243 mnFont = static_cast<sal_uInt16>(rFontCollection.GetId( aFontDesc ));
244 if ( mnFont == nCount )
246 FontCollectionEntry& rFontDesc = rFontCollection.GetLast();
247 if ( ImplGetPropertyValue( "CharFontCharSet", false ) )
248 mAny >>= rFontDesc.CharSet;
249 if ( ImplGetPropertyValue( "CharFontFamily", false ) )
250 mAny >>= rFontDesc.Family;
251 if ( ImplGetPropertyValue( "CharFontPitch", false ) )
252 mAny >>= rFontDesc.Pitch;
256 sal_Int16 nScriptType = SvtLanguageOptions::FromSvtScriptTypeToI18N( SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() ) );
257 if ( mpText && mnTextSize && xPPTBreakIter.is() )
259 OUString sT( reinterpret_cast<sal_Unicode *>(mpText.get()), mnTextSize );
260 nScriptType = xPPTBreakIter->getScriptType( sT, 0 );
262 if ( nScriptType != css::i18n::ScriptType::COMPLEX )
264 bOk = ImplGetPropertyValue( "CharFontNameAsian", bGetPropStateValue );
265 meAsianOrComplexFont = ePropState;
266 if ( bOk )
268 FontCollectionEntry aFontDesc( *o3tl::doAccess<OUString>(mAny) );
269 sal_uInt32 nCount = rFontCollection.GetCount();
270 mnAsianOrComplexFont = static_cast<sal_uInt16>(rFontCollection.GetId( aFontDesc ));
271 if ( mnAsianOrComplexFont == nCount )
273 FontCollectionEntry& rFontDesc = rFontCollection.GetLast();
274 if ( ImplGetPropertyValue( "CharFontCharSetAsian", false ) )
275 mAny >>= rFontDesc.CharSet;
276 if ( ImplGetPropertyValue( "CharFontFamilyAsian", false ) )
277 mAny >>= rFontDesc.Family;
278 if ( ImplGetPropertyValue( "CharFontPitchAsian", false ) )
279 mAny >>= rFontDesc.Pitch;
283 else
285 bOk = ImplGetPropertyValue( "CharFontNameComplex", bGetPropStateValue );
286 meAsianOrComplexFont = ePropState;
287 if ( bOk )
289 FontCollectionEntry aFontDesc( *o3tl::doAccess<OUString>(mAny) );
290 sal_uInt32 nCount = rFontCollection.GetCount();
291 mnAsianOrComplexFont = static_cast<sal_uInt16>(rFontCollection.GetId( aFontDesc ));
292 if ( mnAsianOrComplexFont == nCount )
294 FontCollectionEntry& rFontDesc = rFontCollection.GetLast();
295 if ( ImplGetPropertyValue( "CharFontCharSetComplex", false ) )
296 mAny >>= rFontDesc.CharSet;
297 if ( ImplGetPropertyValue( "CharFontFamilyComplex", false ) )
298 mAny >>= rFontDesc.Family;
299 if ( ImplGetPropertyValue( "CharFontPitchComplex", false ) )
300 mAny >>= rFontDesc.Pitch;
305 OUString aCharHeightName, aCharWeightName, aCharLocaleName, aCharPostureName;
306 switch( nScriptType )
308 case css::i18n::ScriptType::ASIAN :
310 aCharHeightName = "CharHeightAsian";
311 aCharWeightName = "CharWeightAsian";
312 aCharLocaleName = "CharLocaleAsian";
313 aCharPostureName = "CharPostureAsian";
314 break;
316 case css::i18n::ScriptType::COMPLEX :
318 aCharHeightName = "CharHeightComplex";
319 aCharWeightName = "CharWeightComplex";
320 aCharLocaleName = "CharLocaleComplex";
321 aCharPostureName = "CharPostureComplex";
322 break;
324 default:
326 aCharHeightName = "CharHeight";
327 aCharWeightName = "CharWeight";
328 aCharLocaleName = "CharLocale";
329 aCharPostureName = "CharPosture";
330 break;
334 mnCharHeight = 24;
335 if ( GetPropertyValue( mAny, mXPropSet, aCharHeightName ) )
337 float fVal(0.0);
338 if ( mAny >>= fVal )
340 mnCharHeight = static_cast<sal_uInt16>( fVal + 0.5 );
341 meCharHeight = GetPropertyState( mXPropSet, aCharHeightName );
344 if ( GetPropertyValue( mAny, mXPropSet, aCharWeightName ) )
346 float fFloat(0.0);
347 if ( mAny >>= fFloat )
349 if ( fFloat >= css::awt::FontWeight::SEMIBOLD )
350 mnCharAttr |= 1;
351 if ( GetPropertyState( mXPropSet, aCharWeightName ) == css::beans::PropertyState_DIRECT_VALUE )
352 mnCharAttrHard |= 1;
355 if ( GetPropertyValue( mAny, mXPropSet, aCharLocaleName ) )
357 css::lang::Locale eLocale;
358 if ( mAny >>= eLocale )
359 meCharLocale = eLocale;
361 if ( GetPropertyValue( mAny, mXPropSet, aCharPostureName ) )
363 css::awt::FontSlant aFS;
364 if ( mAny >>= aFS )
366 switch( aFS )
368 case css::awt::FontSlant_OBLIQUE :
369 case css::awt::FontSlant_ITALIC :
370 mnCharAttr |= 2;
371 break;
372 default:
373 break;
375 if ( GetPropertyState( mXPropSet, aCharPostureName ) == css::beans::PropertyState_DIRECT_VALUE )
376 mnCharAttrHard |= 2;
380 if ( ImplGetPropertyValue( "CharUnderline", bGetPropStateValue ) )
382 sal_Int16 nVal(0);
383 mAny >>= nVal;
384 switch ( nVal )
386 case css::awt::FontUnderline::SINGLE :
387 case css::awt::FontUnderline::DOUBLE :
388 case css::awt::FontUnderline::DOTTED :
389 mnCharAttr |= 4;
392 if ( ePropState == css::beans::PropertyState_DIRECT_VALUE )
393 mnCharAttrHard |= 4;
395 if ( ImplGetPropertyValue( "CharShadowed", bGetPropStateValue ) )
397 bool bBool(false);
398 mAny >>= bBool;
399 if ( bBool )
400 mnCharAttr |= 0x10;
402 if ( ePropState == css::beans::PropertyState_DIRECT_VALUE )
403 mnCharAttrHard |= 16;
405 if ( ImplGetPropertyValue( "CharRelief", bGetPropStateValue ) )
407 sal_Int16 nVal(0);
408 mAny >>= nVal;
409 if ( nVal != css::text::FontRelief::NONE )
410 mnCharAttr |= 512;
412 if ( ePropState == css::beans::PropertyState_DIRECT_VALUE )
413 mnCharAttrHard |= 512;
415 if ( ImplGetPropertyValue( "CharColor", bGetPropStateValue ) )
417 sal_uInt32 nSOColor = *( o3tl::doAccess<sal_uInt32>(mAny) );
418 mnCharColor = nSOColor & 0xff00ff00; // green and hibyte
419 mnCharColor |= static_cast<sal_uInt8>(nSOColor) << 16; // red and blue is switched
420 mnCharColor |= static_cast<sal_uInt8>( nSOColor >> 16 );
422 meCharColor = ePropState;
424 mnCharEscapement = 0;
425 if ( ImplGetPropertyValue( "CharEscapement", bGetPropStateValue ) )
427 mAny >>= mnCharEscapement;
428 if ( mnCharEscapement > 100 )
429 mnCharEscapement = 33;
430 else if ( mnCharEscapement < -100 )
431 mnCharEscapement = -33;
433 meCharEscapement = ePropState;
436 void PortionObj::ImplClear()
438 mpFieldEntry.reset();
439 mpText.reset();
442 void PortionObj::ImplConstruct( const PortionObj& rPortionObj )
444 meCharColor = rPortionObj.meCharColor;
445 meCharHeight = rPortionObj.meCharHeight;
446 meFontName = rPortionObj.meFontName;
447 meAsianOrComplexFont = rPortionObj.meAsianOrComplexFont;
448 meCharEscapement = rPortionObj.meCharEscapement;
449 meCharLocale = rPortionObj.meCharLocale;
450 mnCharAttrHard = rPortionObj.mnCharAttrHard;
452 mbLastPortion = rPortionObj.mbLastPortion;
453 mnTextSize = rPortionObj.mnTextSize;
454 mnCharColor = rPortionObj.mnCharColor;
455 mnCharEscapement = rPortionObj.mnCharEscapement;
456 mnCharAttr = rPortionObj.mnCharAttr;
457 mnCharHeight = rPortionObj.mnCharHeight;
458 mnFont = rPortionObj.mnFont;
459 mnAsianOrComplexFont = rPortionObj.mnAsianOrComplexFont;
461 if ( rPortionObj.mpText )
463 mpText.reset( new sal_uInt16[ mnTextSize ] );
464 memcpy( mpText.get(), rPortionObj.mpText.get(), mnTextSize << 1 );
467 if ( rPortionObj.mpFieldEntry )
468 mpFieldEntry.reset( new FieldEntry( *( rPortionObj.mpFieldEntry ) ) );
471 sal_uInt32 PortionObj::ImplCalculateTextPositions( sal_uInt32 nCurrentTextPosition )
473 if ( mpFieldEntry && ( !mpFieldEntry->nFieldStartPos ) )
475 mpFieldEntry->nFieldStartPos += nCurrentTextPosition;
476 mpFieldEntry->nFieldEndPos += nCurrentTextPosition;
478 return mnTextSize;
481 // Return: 0 = no TextField
482 // bit28->31 text field type :
483 // 1 = Date
484 // 2 = Time
485 // 3 = SlideNumber
486 // 4 = Url
487 // 5 = DateTime
488 // 6 = header
489 // 7 = footer
490 // bit24->27 text field sub type (optional)
491 // 23-> PPT Textfield needs a placeholder
493 sal_uInt32 PortionObj::ImplGetTextField( css::uno::Reference< css::text::XTextRange > & ,
494 const css::uno::Reference< css::beans::XPropertySet > & rXPropSet, OUString& rURL )
496 sal_uInt32 nRetValue = 0;
497 sal_Int32 nFormat;
498 css::uno::Any aAny;
499 if ( GetPropertyValue( aAny, rXPropSet, "TextPortionType", true ) )
501 auto aTextFieldType = o3tl::doAccess<OUString>(aAny);
502 if ( *aTextFieldType == "TextField" )
504 if ( GetPropertyValue( aAny, rXPropSet, *aTextFieldType, true ) )
506 css::uno::Reference< css::text::XTextField > aXTextField;
507 if ( aAny >>= aXTextField )
509 if ( aXTextField.is() )
511 css::uno::Reference< css::beans::XPropertySet > xFieldPropSet( aXTextField, css::uno::UNO_QUERY );
512 if ( xFieldPropSet.is() )
514 OUString aFieldKind( aXTextField->getPresentation( true ) );
515 if ( aFieldKind == "Date" )
517 if ( GetPropertyValue( aAny, xFieldPropSet, "IsFix", true ) )
519 bool bBool = false;
520 aAny >>= bBool;
521 if ( !bBool ) // Fixed DateFields does not exist in PPT
523 if ( GetPropertyValue( aAny, xFieldPropSet, "Format", true ) )
525 nFormat = *o3tl::doAccess<sal_Int32>(aAny);
526 switch ( nFormat )
528 default:
529 case 5 :
530 case 4 :
531 case 2 : nFormat = 0; break;
532 case 8 :
533 case 9 :
534 case 3 : nFormat = 1; break;
535 case 7 :
536 case 6 : nFormat = 2; break;
538 nRetValue |= ( ( ( 1 << 4 ) | nFormat ) << 24 ) | 0x800000;
543 else if ( aFieldKind == "URL" )
545 if ( GetPropertyValue( aAny, xFieldPropSet, "URL", true ) )
546 rURL = *o3tl::doAccess<OUString>(aAny);
547 nRetValue = 4 << 28;
549 else if ( aFieldKind == "Page" )
551 nRetValue = 3 << 28 | 0x800000;
553 else if ( aFieldKind == "Pages" )
557 else if ( aFieldKind == "Time" )
559 if ( GetPropertyValue( aAny, xFieldPropSet, "IsFix", true ) )
561 bool bBool = false;
562 aAny >>= bBool;
563 if ( !bBool )
565 if ( GetPropertyValue( aAny, xFieldPropSet, "IsFix", true ) )
567 nFormat = *o3tl::doAccess<sal_Int32>(aAny);
568 nRetValue |= ( ( ( 2 << 4 ) | nFormat ) << 24 ) | 0x800000;
573 else if ( aFieldKind == "File" )
577 else if ( aFieldKind == "Table" )
581 else if ( aFieldKind == "ExtTime" )
583 if ( GetPropertyValue( aAny, xFieldPropSet, "IsFix", true ) )
585 bool bBool = false;
586 aAny >>= bBool;
587 if ( !bBool )
589 if ( GetPropertyValue( aAny, xFieldPropSet, "Format", true ) )
591 nFormat = *o3tl::doAccess<sal_Int32>(aAny);
592 switch ( nFormat )
594 default:
595 case 6 :
596 case 7 :
597 case 8 :
598 case 2 : nFormat = 12; break;
599 case 3 : nFormat = 9; break;
600 case 5 :
601 case 4 : nFormat = 10; break;
604 nRetValue |= ( ( ( 2 << 4 ) | nFormat ) << 24 ) | 0x800000;
609 else if ( aFieldKind == "ExtFile" )
613 else if ( aFieldKind == "Author" )
617 else if ( aFieldKind == "DateTime" )
619 nRetValue = 5 << 28 | 0x800000;
621 else if ( aFieldKind == "Header" )
623 nRetValue = 6 << 28 | 0x800000;
625 else if ( aFieldKind == "Footer" )
627 nRetValue = 7 << 28 | 0x800000;
635 return nRetValue;
638 PortionObj& PortionObj::operator=( const PortionObj& rPortionObj )
640 if ( this != &rPortionObj )
642 ImplClear();
643 ImplConstruct( rPortionObj );
645 return *this;
648 ParagraphObj::ParagraphObj(const css::uno::Reference< css::beans::XPropertySet > & rXPropSet,
649 PPTExBulletProvider* pProv)
650 : PropStateValue()
651 , SOParagraph()
652 , mvPortions()
653 , mnTextSize(0)
654 , mbFirstParagraph(false)
655 , mbLastParagraph(false)
656 , mnTextAdjust(0)
657 , mnLineSpacing(0)
658 , mbFixedLineSpacing(false)
659 , mnLineSpacingTop(0)
660 , mnLineSpacingBottom(0)
661 , mbForbiddenRules(false)
662 , mbParagraphPunctation(false)
663 , mnBiDi(0)
665 mXPropSet = rXPropSet;
667 bExtendedParameters = false;
669 nDepth = 0;
670 nBulletFlags = 0;
671 nParaFlags = 0;
673 ImplGetParagraphValues( pProv, false );
676 ParagraphObj::ParagraphObj(css::uno::Reference< css::text::XTextContent > const & rXTextContent,
677 ParaFlags aParaFlags, FontCollection& rFontCollection, PPTExBulletProvider& rProv )
678 : PropStateValue()
679 , SOParagraph()
680 , mvPortions()
681 , mnTextSize(0)
682 , mbIsBullet(false)
683 , mbFirstParagraph( aParaFlags.bFirstParagraph )
684 , mbLastParagraph( aParaFlags.bLastParagraph )
685 , meBullet(css::beans::PropertyState_AMBIGUOUS_VALUE)
686 , meTextAdjust(css::beans::PropertyState_AMBIGUOUS_VALUE)
687 , meLineSpacing(css::beans::PropertyState_AMBIGUOUS_VALUE)
688 , meLineSpacingTop(css::beans::PropertyState_AMBIGUOUS_VALUE)
689 , meLineSpacingBottom(css::beans::PropertyState_AMBIGUOUS_VALUE)
690 , meForbiddenRules(css::beans::PropertyState_AMBIGUOUS_VALUE)
691 , meParagraphPunctation(css::beans::PropertyState_AMBIGUOUS_VALUE)
692 , meBiDi(css::beans::PropertyState_AMBIGUOUS_VALUE)
693 , mnTextAdjust(0)
694 , mnLineSpacing(0)
695 , mbFixedLineSpacing(false)
696 , mnLineSpacingTop(0)
697 , mnLineSpacingBottom(0)
698 , mbForbiddenRules(false)
699 , mbParagraphPunctation(false)
700 , mnBiDi(0)
702 bExtendedParameters = false;
704 nDepth = 0;
705 nBulletFlags = 0;
706 nParaFlags = 0;
708 mXPropSet.set( rXTextContent, css::uno::UNO_QUERY );
710 mXPropState.set( rXTextContent, css::uno::UNO_QUERY );
712 if ( !(mXPropSet.is() && mXPropState.is()) )
713 return;
715 css::uno::Reference< css::container::XEnumerationAccess > aXTextPortionEA( rXTextContent, css::uno::UNO_QUERY );
716 if ( aXTextPortionEA.is() )
718 css::uno::Reference< css::container::XEnumeration > aXTextPortionE( aXTextPortionEA->createEnumeration() );
719 if ( aXTextPortionE.is() )
721 while ( aXTextPortionE->hasMoreElements() )
723 css::uno::Reference< css::text::XTextRange > aXCursorText;
724 css::uno::Any aAny( aXTextPortionE->nextElement() );
725 if ( aAny >>= aXCursorText )
727 std::unique_ptr<PortionObj> pPortionObj(new PortionObj( aXCursorText, !aXTextPortionE->hasMoreElements(), rFontCollection ));
728 if ( pPortionObj->Count() )
729 mvPortions.push_back( std::move(pPortionObj) );
734 ImplGetParagraphValues( &rProv, true );
737 ParagraphObj::~ParagraphObj()
739 ImplClear();
742 void ParagraphObj::Write( SvStream* pStrm )
744 for ( std::vector<std::unique_ptr<PortionObj> >::iterator it = mvPortions.begin(); it != mvPortions.end(); ++it )
745 (*it)->Write( pStrm, mbLastParagraph );
748 void ParagraphObj::ImplClear()
750 mvPortions.clear();
753 void ParagraphObj::CalculateGraphicBulletSize( sal_uInt16 nFontHeight )
755 if ( !(( nNumberingType == SVX_NUM_BITMAP ) && ( nBulletId != 0xffff )) )
756 return;
758 // calculate the bullet real size for this graphic
759 if ( aBuGraSize.Width() && aBuGraSize.Height() )
761 double fCharHeight = nFontHeight;
762 double fLen = aBuGraSize.Height();
763 fCharHeight = fCharHeight * 0.2540;
764 double fQuo = fLen / fCharHeight;
765 nBulletRealSize = static_cast<sal_Int16>( fQuo + 0.5 );
766 if ( static_cast<sal_uInt16>(nBulletRealSize) > 400 )
767 nBulletRealSize = 400;
771 void ParagraphObj::ImplGetNumberingLevel( PPTExBulletProvider* pBuProv, sal_Int16 nNumberingDepth, bool bIsBullet, bool bGetPropStateValue )
773 css::uno::Any aAny;
774 if ( GetPropertyValue( aAny, mXPropSet, "ParaLeftMargin" ) )
776 sal_Int32 nVal(0);
777 if ( aAny >>= nVal )
778 nTextOfs = static_cast< sal_Int16 >( nVal / ( 2540.0 / 576 ) + 0.5 ) ;
780 if ( GetPropertyValue( aAny, mXPropSet, "ParaFirstLineIndent" ) )
782 if ( aAny >>= nBulletOfs )
783 nBulletOfs = static_cast< sal_Int32 >( nBulletOfs / ( 2540.0 / 576 ) + 0.5 );
785 if ( GetPropertyValue( aAny, mXPropSet, "NumberingIsNumber" ) )
786 aAny >>= bNumberingIsNumber;
788 css::uno::Reference< css::container::XIndexReplace > aXIndexReplace;
790 if ( bIsBullet && ImplGetPropertyValue( "NumberingRules", bGetPropStateValue ) )
792 if ( ( mAny >>= aXIndexReplace ) && nNumberingDepth < aXIndexReplace->getCount() )
794 mAny = aXIndexReplace->getByIndex( nNumberingDepth );
795 auto aPropertySequence = o3tl::doAccess<css::uno::Sequence<css::beans::PropertyValue>>(mAny);
797 const css::beans::PropertyValue* pPropValue = aPropertySequence->getConstArray();
799 sal_Int32 nPropertyCount = aPropertySequence->getLength();
800 if ( nPropertyCount )
802 bExtendedParameters = true;
803 nBulletRealSize = 100;
804 nMappedNumType = 0;
806 uno::Reference<graphic::XGraphic> xGraphic;
807 for ( sal_Int32 i = 0; i < nPropertyCount; i++ )
809 OUString aPropName( pPropValue[ i ].Name );
810 if ( aPropName == "NumberingType" )
811 nNumberingType = static_cast<SvxNumType>(*o3tl::doAccess<sal_Int16>(pPropValue[i].Value));
812 else if ( aPropName == "Adjust" )
813 nHorzAdjust = *o3tl::doAccess<sal_Int16>(pPropValue[i].Value);
814 else if ( aPropName == "BulletChar" )
816 OUString aString( *o3tl::doAccess<OUString>(pPropValue[i].Value) );
817 if ( !aString.isEmpty() )
818 cBulletId = aString[ 0 ];
820 else if ( aPropName == "BulletFont" )
822 aFontDesc = *o3tl::doAccess<css::awt::FontDescriptor>(pPropValue[i].Value);
824 // Our numbullet dialog has set the wrong textencoding for our "StarSymbol" font,
825 // instead of a Unicode encoding the encoding RTL_TEXTENCODING_SYMBOL was used.
826 // Because there might exist a lot of damaged documemts I added this two lines
827 // which fixes the bullet problem for the export.
828 if ( aFontDesc.Name.equalsIgnoreAsciiCase("StarSymbol") )
829 aFontDesc.CharSet = RTL_TEXTENCODING_MS_1252;
832 else if ( aPropName == "GraphicBitmap" )
834 auto xBitmap = pPropValue[i].Value.get<uno::Reference<awt::XBitmap>>();
835 xGraphic.set(xBitmap, uno::UNO_QUERY);
837 else if ( aPropName == "GraphicSize" )
839 if (auto aSize = o3tl::tryAccess<css::awt::Size>(pPropValue[i].Value))
841 // don't cast awt::Size to Size as on 64-bits they are not the same.
842 aBuGraSize.setWidth( aSize->Width );
843 aBuGraSize.setHeight( aSize->Height );
846 else if ( aPropName == "StartWith" )
847 nStartWith = *o3tl::doAccess<sal_Int16>(pPropValue[i].Value);
848 else if ( aPropName == "LeftMargin" )
849 nTextOfs = nTextOfs + static_cast< sal_Int16 >( *o3tl::doAccess<sal_Int32>(pPropValue[i].Value) / ( 2540.0 / 576 ) );
850 else if ( aPropName == "FirstLineOffset" )
851 nBulletOfs += static_cast<sal_Int16>( *o3tl::doAccess<sal_Int32>(pPropValue[i].Value) / ( 2540.0 / 576 ) );
852 else if ( aPropName == "BulletColor" )
854 sal_uInt32 nSOColor = *o3tl::doAccess<sal_uInt32>(pPropValue[i].Value);
855 nBulletColor = nSOColor & 0xff00ff00; // green and hibyte
856 nBulletColor |= static_cast<sal_uInt8>(nSOColor) << 16; // red
857 nBulletColor |= static_cast<sal_uInt8>( nSOColor >> 16 ) | 0xfe000000; // blue
859 else if ( aPropName == "BulletRelSize" )
861 nBulletRealSize = *o3tl::doAccess<sal_Int16>(pPropValue[i].Value);
862 nParaFlags |= 0x40;
863 nBulletFlags |= 8;
865 else if ( aPropName == "Prefix" )
866 sPrefix = *o3tl::doAccess<OUString>(pPropValue[i].Value);
867 else if ( aPropName == "Suffix" )
868 sSuffix = *o3tl::doAccess<OUString>(pPropValue[i].Value);
869 #ifdef DBG_UTIL
870 else if ( ! (
871 ( aPropName == "SymbolTextDistance" )
872 || ( aPropName == "GraphicBitmap" ) ) )
874 OSL_FAIL( "Unknown Property" );
876 #endif
879 if (xGraphic.is())
881 if ( aBuGraSize.Width() && aBuGraSize.Height() )
883 Graphic aGraphic(xGraphic);
884 nBulletId = pBuProv->GetId(xGraphic, aBuGraSize );
885 if ( nBulletId != 0xffff )
886 bExtendedBulletsUsed = true;
888 else
890 nNumberingType = SVX_NUM_NUMBER_NONE;
894 CalculateGraphicBulletSize( ( mvPortions.empty() ) ? 24 : mvPortions.front()->mnCharHeight );
896 switch( nNumberingType )
898 case SVX_NUM_NUMBER_NONE : nParaFlags |= 0xf; break;
900 case SVX_NUM_CHAR_SPECIAL : // Bullet
902 if ( IsStarSymbol(aFontDesc.Name) )
904 rtl_TextEncoding eChrSet = aFontDesc.CharSet;
905 cBulletId = msfilter::util::bestFitOpenSymbolToMSFont(cBulletId, eChrSet, aFontDesc.Name);
906 aFontDesc.CharSet = eChrSet;
909 if ( !aFontDesc.Name.isEmpty() )
911 nParaFlags |= 0x90; // we define the font and charset
914 [[fallthrough]];
916 case SVX_NUM_CHARS_UPPER_LETTER : // count from a-z, aa - az, ba - bz, ...
917 case SVX_NUM_CHARS_LOWER_LETTER :
918 case SVX_NUM_ROMAN_UPPER :
919 case SVX_NUM_ROMAN_LOWER :
920 case SVX_NUM_ARABIC :
921 case SVX_NUM_PAGEDESC : // numbering from the page template
922 case SVX_NUM_BITMAP :
923 case SVX_NUM_CHARS_UPPER_LETTER_N : // count from a-z, aa-zz, aaa-zzz
924 case SVX_NUM_CHARS_LOWER_LETTER_N :
925 case SVX_NUM_NUMBER_UPPER_ZH:
926 case SVX_NUM_CIRCLE_NUMBER:
927 case SVX_NUM_NUMBER_UPPER_ZH_TW:
928 case SVX_NUM_NUMBER_LOWER_ZH:
929 case SVX_NUM_FULL_WIDTH_ARABIC:
931 if ( nNumberingType != SVX_NUM_CHAR_SPECIAL )
933 bExtendedBulletsUsed = true;
934 if ( nNumberingDepth & 1 )
935 cBulletId = 0x2013; // defaulting bullet characters for ppt97
936 else if ( nNumberingDepth == 4 )
937 cBulletId = 0xbb;
938 else
939 cBulletId = 0x2022;
941 switch( nNumberingType )
943 case SVX_NUM_CHARS_UPPER_LETTER :
944 case SVX_NUM_CHARS_UPPER_LETTER_N :
946 if ( sSuffix == ")" )
948 if ( sPrefix == "(" )
949 nMappedNumType = 0xa0001; // (A)
950 else
951 nMappedNumType = 0xb0001; // A)
953 else
954 nMappedNumType = 0x10001; // A.
956 break;
957 case SVX_NUM_CHARS_LOWER_LETTER :
958 case SVX_NUM_CHARS_LOWER_LETTER_N :
960 if ( sSuffix == ")" )
962 if ( sPrefix == "(" )
963 nMappedNumType = 0x80001; // (a)
964 else
965 nMappedNumType = 0x90001; // a)
967 else
968 nMappedNumType = 0x00001; // a.
970 break;
971 case SVX_NUM_ROMAN_UPPER :
973 if ( sSuffix == ")" )
975 if ( sPrefix == "(" )
976 nMappedNumType = 0xe0001; // (I)
977 else
978 nMappedNumType = 0xf0001; // I)
980 else
981 nMappedNumType = 0x70001; // I.
983 break;
984 case SVX_NUM_ROMAN_LOWER :
986 if ( sSuffix == ")" )
988 if ( sPrefix == "(" )
989 nMappedNumType = 0x40001; // (i)
990 else
991 nMappedNumType = 0x50001; // i)
993 else
994 nMappedNumType = 0x60001; // i.
996 break;
997 case SVX_NUM_ARABIC :
999 if ( sSuffix == ")" )
1001 if ( sPrefix == "(" )
1002 nMappedNumType = 0xc0001; // (1)
1003 else
1004 nMappedNumType = 0x20001; // 1)
1006 else
1008 if ( sSuffix.isEmpty() && sPrefix.isEmpty() )
1009 nMappedNumType = 0xd0001; // 1
1010 else
1011 nMappedNumType = 0x30001; // 1.
1014 break;
1015 case SVX_NUM_NUMBER_UPPER_ZH :
1017 if ( !sSuffix.isEmpty() )
1018 nMappedNumType = 0x110001; // Simplified Chinese with single-byte period.
1019 else
1020 nMappedNumType = 0x100001; // Simplified Chinese.
1022 break;
1023 case SVX_NUM_CIRCLE_NUMBER :
1025 nMappedNumType = 0x120001; // Double byte circle numbers.
1027 break;
1028 case SVX_NUM_NUMBER_UPPER_ZH_TW :
1030 if ( !sSuffix.isEmpty() )
1031 nMappedNumType = 0x160001; // Traditional Chinese with single-byte period.
1032 else
1033 nMappedNumType = 0x150001; // Traditional Chinese.
1035 break;
1036 case SVX_NUM_NUMBER_LOWER_ZH :
1038 if ( sSuffix == OUStringLiteral1(0xff0e) )
1039 nMappedNumType = 0x260001; // Japanese with double-byte period.
1040 else if ( !sSuffix.isEmpty() )
1041 nMappedNumType = 0x1B0001; // Japanese/Korean with single-byte period.
1042 else
1043 nMappedNumType = 0x1A0001; // Japanese/Korean.
1045 break;
1046 case SVX_NUM_FULL_WIDTH_ARABIC :
1048 if ( !sSuffix.isEmpty() )
1049 nMappedNumType = 0x1D0001; // Double-byte Arabic numbers with double-byte period.
1050 else
1051 nMappedNumType = 0x1C0001; // Double-byte Arabic numbers.
1053 break;
1054 default:
1055 break;
1058 nParaFlags |= 0x2f;
1059 nBulletFlags |= 6;
1060 if ( mbIsBullet && bNumberingIsNumber )
1061 nBulletFlags |= 1;
1062 break;
1064 default:
1065 break;
1070 nBulletOfs = nTextOfs + nBulletOfs;
1071 if ( nBulletOfs < 0 )
1072 nBulletOfs = 0;
1075 void ParagraphObj::ImplGetParagraphValues( PPTExBulletProvider* pBuProv, bool bGetPropStateValue )
1077 css::uno::Any aAny;
1078 if ( GetPropertyValue( aAny, mXPropSet, "NumberingLevel", true ) )
1080 if ( bGetPropStateValue )
1081 meBullet = GetPropertyState( mXPropSet, "NumberingLevel" );
1082 nDepth = *o3tl::doAccess<sal_Int16>(aAny);
1084 if ( nDepth < 0 )
1086 mbIsBullet = false;
1087 nDepth = 0;
1089 else
1091 if ( nDepth > 4 )
1092 nDepth = 4;
1093 mbIsBullet = true;
1096 else
1098 nDepth = 0;
1099 mbIsBullet = false;
1101 ImplGetNumberingLevel( pBuProv, nDepth, mbIsBullet, bGetPropStateValue );
1103 if ( ImplGetPropertyValue( "ParaTabStops", bGetPropStateValue ) )
1104 maTabStop = *o3tl::doAccess<css::uno::Sequence<css::style::TabStop>>(mAny);
1105 sal_Int16 eTextAdjust = sal_Int16(css::style::ParagraphAdjust_LEFT);
1106 if ( GetPropertyValue( aAny, mXPropSet, "ParaAdjust", bGetPropStateValue ) )
1107 aAny >>= eTextAdjust;
1108 switch ( static_cast<css::style::ParagraphAdjust>(eTextAdjust) )
1110 case css::style::ParagraphAdjust_CENTER :
1111 mnTextAdjust = 1;
1112 break;
1113 case css::style::ParagraphAdjust_RIGHT :
1114 mnTextAdjust = 2;
1115 break;
1116 case css::style::ParagraphAdjust_BLOCK :
1117 mnTextAdjust = 3;
1118 break;
1119 default :
1120 case css::style::ParagraphAdjust_LEFT :
1121 mnTextAdjust = 0;
1122 break;
1124 meTextAdjust = ePropState;
1126 if ( ImplGetPropertyValue( "ParaLineSpacing", bGetPropStateValue ) )
1128 css::style::LineSpacing aLineSpacing
1129 = *o3tl::doAccess<css::style::LineSpacing>(mAny);
1130 switch ( aLineSpacing.Mode )
1132 case css::style::LineSpacingMode::FIX :
1133 mnLineSpacing = static_cast<sal_Int16>(-( aLineSpacing.Height ) );
1134 mbFixedLineSpacing = true;
1135 break;
1136 case css::style::LineSpacingMode::MINIMUM :
1137 case css::style::LineSpacingMode::LEADING :
1138 mnLineSpacing = static_cast<sal_Int16>(-( aLineSpacing.Height ) );
1139 mbFixedLineSpacing = false;
1140 break;
1142 case css::style::LineSpacingMode::PROP :
1143 default:
1144 mnLineSpacing = static_cast<sal_Int16>( aLineSpacing.Height );
1145 break;
1148 meLineSpacing = ePropState;
1150 if ( ImplGetPropertyValue( "ParaBottomMargin", bGetPropStateValue ) )
1152 double fSpacing = *o3tl::doAccess<sal_uInt32>(mAny) + ( 2540.0 / 576.0 ) - 1;
1153 mnLineSpacingBottom = static_cast<sal_Int16>(-( fSpacing * 576.0 / 2540.0 ) );
1155 meLineSpacingBottom = ePropState;
1157 if ( ImplGetPropertyValue( "ParaTopMargin", bGetPropStateValue ) )
1159 double fSpacing = *o3tl::doAccess<sal_uInt32>(mAny) + ( 2540.0 / 576.0 ) - 1;
1160 mnLineSpacingTop = static_cast<sal_Int16>(-( fSpacing * 576.0 / 2540.0 ) );
1162 meLineSpacingTop = ePropState;
1164 if ( ImplGetPropertyValue( "ParaIsForbiddenRules", bGetPropStateValue ) )
1165 mAny >>= mbForbiddenRules;
1166 meForbiddenRules = ePropState;
1168 if ( ImplGetPropertyValue( "ParaIsHangingPunctuation", bGetPropStateValue ) )
1169 mAny >>= mbParagraphPunctation;
1170 meParagraphPunctation = ePropState;
1172 mnBiDi = 0;
1173 if ( ImplGetPropertyValue( "WritingMode", bGetPropStateValue ) )
1175 sal_Int16 nWritingMode = 0;
1176 mAny >>= nWritingMode;
1178 SvxFrameDirection eWritingMode = static_cast<SvxFrameDirection>(nWritingMode);
1179 if ( ( eWritingMode == SvxFrameDirection::Horizontal_RL_TB )
1180 || ( eWritingMode == SvxFrameDirection::Vertical_RL_TB ) )
1182 mnBiDi = 1;
1185 meBiDi = ePropState;
1188 void ParagraphObj::ImplConstruct( const ParagraphObj& rParagraphObj )
1190 mbIsBullet = rParagraphObj.mbIsBullet;
1191 meBullet = rParagraphObj.meBullet;
1192 meTextAdjust = rParagraphObj.meTextAdjust;
1193 meLineSpacing = rParagraphObj.meLineSpacing;
1194 meLineSpacingTop = rParagraphObj.meLineSpacingTop;
1195 meLineSpacingBottom = rParagraphObj.meLineSpacingBottom;
1196 meForbiddenRules = rParagraphObj.meForbiddenRules;
1197 meParagraphPunctation = rParagraphObj.meParagraphPunctation;
1198 meBiDi =rParagraphObj.meBiDi;
1199 mbFixedLineSpacing = rParagraphObj.mbFixedLineSpacing;
1200 mnTextSize = rParagraphObj.mnTextSize;
1201 mnTextAdjust = rParagraphObj.mnTextAdjust;
1202 mnLineSpacing = rParagraphObj.mnLineSpacing;
1203 mnLineSpacingTop = rParagraphObj.mnLineSpacingTop;
1204 mnLineSpacingBottom = rParagraphObj.mnLineSpacingBottom;
1205 mbFirstParagraph = rParagraphObj.mbFirstParagraph;
1206 mbLastParagraph = rParagraphObj.mbLastParagraph;
1207 mbParagraphPunctation = rParagraphObj.mbParagraphPunctation;
1208 mbForbiddenRules = rParagraphObj.mbForbiddenRules;
1209 mnBiDi = rParagraphObj.mnBiDi;
1211 for ( std::vector<std::unique_ptr<PortionObj> >::const_iterator it = rParagraphObj.begin(); it != rParagraphObj.end(); ++it )
1212 mvPortions.push_back( std::make_unique<PortionObj>( **it ) );
1214 maTabStop = rParagraphObj.maTabStop;
1215 bExtendedParameters = rParagraphObj.bExtendedParameters;
1216 nParaFlags = rParagraphObj.nParaFlags;
1217 nBulletFlags = rParagraphObj.nBulletFlags;
1218 sPrefix = rParagraphObj.sPrefix;
1219 sSuffix = rParagraphObj.sSuffix;
1220 sGraphicUrl = rParagraphObj.sGraphicUrl; // String to a graphic
1221 aBuGraSize = rParagraphObj.aBuGraSize;
1222 nNumberingType = rParagraphObj.nNumberingType; // this is actually a SvxEnum
1223 nHorzAdjust = rParagraphObj.nHorzAdjust;
1224 nBulletColor = rParagraphObj.nBulletColor;
1225 nBulletOfs = rParagraphObj.nBulletOfs;
1226 nStartWith = rParagraphObj.nStartWith; // start of numbering
1227 nTextOfs = rParagraphObj.nTextOfs;
1228 nBulletRealSize = rParagraphObj.nBulletRealSize; // scale in percent
1229 nDepth = rParagraphObj.nDepth; // actual depth
1230 cBulletId = rParagraphObj.cBulletId; // if Numbering Type == CharSpecial
1231 aFontDesc = rParagraphObj.aFontDesc;
1233 bExtendedBulletsUsed = rParagraphObj.bExtendedBulletsUsed;
1234 nBulletId = rParagraphObj.nBulletId;
1237 sal_uInt32 ParagraphObj::ImplCalculateTextPositions( sal_uInt32 nCurrentTextPosition )
1239 mnTextSize = 0;
1240 for ( std::vector<std::unique_ptr<PortionObj> >::iterator it = mvPortions.begin(); it != mvPortions.end(); ++it )
1241 mnTextSize += (*it)->ImplCalculateTextPositions( nCurrentTextPosition + mnTextSize );
1242 return mnTextSize;
1245 ParagraphObj& ParagraphObj::operator=( const ParagraphObj& rParagraphObj )
1247 if ( this != &rParagraphObj )
1249 ImplClear();
1250 ImplConstruct( rParagraphObj );
1252 return *this;
1255 struct ImplTextObj
1257 sal_uInt32 mnTextSize;
1258 int mnInstance;
1259 std::vector<std::unique_ptr<ParagraphObj>> maList;
1260 bool mbHasExtendedBullets;
1262 explicit ImplTextObj( int nInstance );
1265 ImplTextObj::ImplTextObj( int nInstance )
1266 : maList()
1268 mnTextSize = 0;
1269 mnInstance = nInstance;
1270 mbHasExtendedBullets = false;
1273 TextObj::TextObj( css::uno::Reference< css::text::XSimpleText > const & rXTextRef,
1274 int nInstance, FontCollection& rFontCollection, PPTExBulletProvider& rProv ):
1275 mpImplTextObj(new ImplTextObj(nInstance))
1277 css::uno::Reference< css::container::XEnumerationAccess > aXTextParagraphEA( rXTextRef, css::uno::UNO_QUERY );
1279 if ( aXTextParagraphEA.is() )
1281 css::uno::Reference< css::container::XEnumeration > aXTextParagraphE( aXTextParagraphEA->createEnumeration() );
1282 if ( aXTextParagraphE.is() )
1284 ParaFlags aParaFlags;
1285 while ( aXTextParagraphE->hasMoreElements() )
1287 css::uno::Reference< css::text::XTextContent > aXParagraph;
1288 css::uno::Any aAny( aXTextParagraphE->nextElement() );
1289 if ( aAny >>= aXParagraph )
1291 if ( !aXTextParagraphE->hasMoreElements() )
1292 aParaFlags.bLastParagraph = true;
1293 std::unique_ptr<ParagraphObj> pPara(new ParagraphObj( aXParagraph, aParaFlags, rFontCollection, rProv ));
1294 mpImplTextObj->mbHasExtendedBullets |= pPara->bExtendedBulletsUsed;
1295 mpImplTextObj->maList.push_back( std::move(pPara) );
1296 aParaFlags.bFirstParagraph = false;
1301 ImplCalculateTextPositions();
1304 void TextObj::ImplCalculateTextPositions()
1306 mpImplTextObj->mnTextSize = 0;
1307 for ( sal_uInt32 i = 0; i < ParagraphCount(); ++i )
1308 mpImplTextObj->mnTextSize += GetParagraph(i)->ImplCalculateTextPositions( mpImplTextObj->mnTextSize );
1311 ParagraphObj* TextObj::GetParagraph(int idx)
1313 return mpImplTextObj->maList[idx].get();
1316 sal_uInt32 TextObj::ParagraphCount() const
1318 return mpImplTextObj->maList.size();
1321 sal_uInt32 TextObj::Count() const
1323 return mpImplTextObj->mnTextSize;
1326 int TextObj::GetInstance() const
1328 return mpImplTextObj->mnInstance;
1331 bool TextObj::HasExtendedBullets()
1333 return mpImplTextObj->mbHasExtendedBullets;
1336 FontCollectionEntry::~FontCollectionEntry()
1340 void FontCollectionEntry::ImplInit( const OUString& rName )
1342 OUString aSubstName( GetSubsFontName( rName, SubsFontFlags::ONLYONE | SubsFontFlags::MS ) );
1343 if ( !aSubstName.isEmpty() )
1345 Name = aSubstName;
1347 else
1349 Name = rName;
1353 FontCollection::~FontCollection()
1355 pVDev.disposeAndClear();
1356 xPPTBreakIter = nullptr;
1359 FontCollection::FontCollection() :
1360 pVDev ( nullptr )
1362 xPPTBreakIter = css::i18n::BreakIterator::create( ::comphelper::getProcessComponentContext() );
1365 short FontCollection::GetScriptDirection( const OUString& rString )
1367 short nRet = ScriptTypeDetector::getScriptDirection( rString, 0, css::i18n::ScriptDirection::NEUTRAL );
1368 return nRet;
1371 sal_uInt32 FontCollection::GetId( FontCollectionEntry& rEntry )
1373 if( !rEntry.Name.isEmpty() )
1375 const sal_uInt32 nFonts = maFonts.size();
1377 for( sal_uInt32 i = 0; i < nFonts; i++ )
1379 const FontCollectionEntry* pEntry = GetById( i );
1380 if( pEntry->Name == rEntry.Name )
1381 return i;
1383 vcl::Font aFont;
1384 aFont.SetCharSet( rEntry.CharSet );
1385 aFont.SetFamilyName( rEntry.Original );
1386 aFont.SetFontHeight( 100 );
1388 if ( !pVDev )
1389 pVDev = VclPtr<VirtualDevice>::Create();
1391 pVDev->SetFont( aFont );
1392 FontMetric aMetric( pVDev->GetFontMetric() );
1394 sal_uInt16 nTxtHeight = static_cast<sal_uInt16>(aMetric.GetAscent()) + static_cast<sal_uInt16>(aMetric.GetDescent());
1396 if ( nTxtHeight )
1398 double fScaling = static_cast<double>(nTxtHeight) / 120.0;
1399 if ( ( fScaling > 0.50 ) && ( fScaling < 1.5 ) )
1400 rEntry.Scaling = fScaling;
1403 maFonts.push_back(rEntry);
1404 return nFonts;
1406 return 0;
1409 const FontCollectionEntry* FontCollection::GetById( sal_uInt32 nId )
1411 return nId < maFonts.size() ? &maFonts[nId] : nullptr;
1414 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */