1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
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
)
72 , mnAsianOrComplexFont(0xffff)
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
)
93 , mnAsianOrComplexFont(0xffff)
95 , mbLastPortion(bLast
)
97 OUString
aString( rXTextRange
->getString() );
100 mnTextSize
= aString
.getLength();
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
);
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;
132 if ( nCharset
== css::awt::CharSet::SYMBOL
)
135 if ( mpFieldEntry
&& ( nFieldType
& 0x800000 ) ) // placeholder ?
140 mpText
.reset( new sal_uInt16
[ mnTextSize
] );
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
)
152 bRTL_endingParen
= true;
154 mpText
.reset( new sal_uInt16
[ mnTextSize
] );
156 for ( sal_Int32 i
= 0; i
< aString
.getLength(); i
++ )
158 nChar
= static_cast<sal_uInt16
>(aString
[ i
]);
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
204 if ( bRTL_endingParen
)
205 mpText
[ mnTextSize
- 2 ] = 0x200F; // Unicode Right-to-Left mark
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()
225 void PortionObj::Write( SvStream
* pStrm
, bool bLast
)
227 sal_uInt32 nCount
= mnTextSize
;
228 if ( bLast
&& mbLastPortion
)
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
;
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
;
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
;
285 bOk
= ImplGetPropertyValue( "CharFontNameComplex", bGetPropStateValue
);
286 meAsianOrComplexFont
= ePropState
;
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";
316 case css::i18n::ScriptType::COMPLEX
:
318 aCharHeightName
= "CharHeightComplex";
319 aCharWeightName
= "CharWeightComplex";
320 aCharLocaleName
= "CharLocaleComplex";
321 aCharPostureName
= "CharPostureComplex";
326 aCharHeightName
= "CharHeight";
327 aCharWeightName
= "CharWeight";
328 aCharLocaleName
= "CharLocale";
329 aCharPostureName
= "CharPosture";
335 if ( GetPropertyValue( mAny
, mXPropSet
, aCharHeightName
) )
340 mnCharHeight
= static_cast<sal_uInt16
>( fVal
+ 0.5 );
341 meCharHeight
= GetPropertyState( mXPropSet
, aCharHeightName
);
344 if ( GetPropertyValue( mAny
, mXPropSet
, aCharWeightName
) )
347 if ( mAny
>>= fFloat
)
349 if ( fFloat
>= css::awt::FontWeight::SEMIBOLD
)
351 if ( GetPropertyState( mXPropSet
, aCharWeightName
) == css::beans::PropertyState_DIRECT_VALUE
)
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
;
368 case css::awt::FontSlant_OBLIQUE
:
369 case css::awt::FontSlant_ITALIC
:
375 if ( GetPropertyState( mXPropSet
, aCharPostureName
) == css::beans::PropertyState_DIRECT_VALUE
)
380 if ( ImplGetPropertyValue( "CharUnderline", bGetPropStateValue
) )
386 case css::awt::FontUnderline::SINGLE
:
387 case css::awt::FontUnderline::DOUBLE
:
388 case css::awt::FontUnderline::DOTTED
:
392 if ( ePropState
== css::beans::PropertyState_DIRECT_VALUE
)
395 if ( ImplGetPropertyValue( "CharShadowed", bGetPropStateValue
) )
402 if ( ePropState
== css::beans::PropertyState_DIRECT_VALUE
)
403 mnCharAttrHard
|= 16;
405 if ( ImplGetPropertyValue( "CharRelief", bGetPropStateValue
) )
409 if ( nVal
!= css::text::FontRelief::NONE
)
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();
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
;
481 // Return: 0 = no TextField
482 // bit28->31 text field type :
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;
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 ) )
521 if ( !bBool
) // Fixed DateFields does not exist in PPT
523 if ( GetPropertyValue( aAny
, xFieldPropSet
, "Format", true ) )
525 nFormat
= *o3tl::doAccess
<sal_Int32
>(aAny
);
531 case 2 : nFormat
= 0; break;
534 case 3 : nFormat
= 1; break;
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
);
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 ) )
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 ) )
589 if ( GetPropertyValue( aAny
, xFieldPropSet
, "Format", true ) )
591 nFormat
= *o3tl::doAccess
<sal_Int32
>(aAny
);
598 case 2 : nFormat
= 12; break;
599 case 3 : nFormat
= 9; break;
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;
638 PortionObj
& PortionObj::operator=( const PortionObj
& rPortionObj
)
640 if ( this != &rPortionObj
)
643 ImplConstruct( rPortionObj
);
648 ParagraphObj::ParagraphObj(const css::uno::Reference
< css::beans::XPropertySet
> & rXPropSet
,
649 PPTExBulletProvider
* pProv
)
654 , mbFirstParagraph(false)
655 , mbLastParagraph(false)
658 , mbFixedLineSpacing(false)
659 , mnLineSpacingTop(0)
660 , mnLineSpacingBottom(0)
661 , mbForbiddenRules(false)
662 , mbParagraphPunctation(false)
665 mXPropSet
= rXPropSet
;
667 bExtendedParameters
= false;
673 ImplGetParagraphValues( pProv
, false );
676 ParagraphObj::ParagraphObj(css::uno::Reference
< css::text::XTextContent
> const & rXTextContent
,
677 ParaFlags aParaFlags
, FontCollection
& rFontCollection
, PPTExBulletProvider
& rProv
)
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
)
695 , mbFixedLineSpacing(false)
696 , mnLineSpacingTop(0)
697 , mnLineSpacingBottom(0)
698 , mbForbiddenRules(false)
699 , mbParagraphPunctation(false)
702 bExtendedParameters
= false;
708 mXPropSet
.set( rXTextContent
, css::uno::UNO_QUERY
);
710 mXPropState
.set( rXTextContent
, css::uno::UNO_QUERY
);
712 if ( !(mXPropSet
.is() && mXPropState
.is()) )
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()
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()
753 void ParagraphObj::CalculateGraphicBulletSize( sal_uInt16 nFontHeight
)
755 if ( !(( nNumberingType
== SVX_NUM_BITMAP
) && ( nBulletId
!= 0xffff )) )
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
)
774 if ( GetPropertyValue( aAny
, mXPropSet
, "ParaLeftMargin" ) )
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;
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
);
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
);
871 ( aPropName
== "SymbolTextDistance" )
872 || ( aPropName
== "GraphicBitmap" ) ) )
874 OSL_FAIL( "Unknown Property" );
881 if ( aBuGraSize
.Width() && aBuGraSize
.Height() )
883 Graphic
aGraphic(xGraphic
);
884 nBulletId
= pBuProv
->GetId(xGraphic
, aBuGraSize
);
885 if ( nBulletId
!= 0xffff )
886 bExtendedBulletsUsed
= true;
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
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 )
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)
951 nMappedNumType
= 0xb0001; // A)
954 nMappedNumType
= 0x10001; // A.
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)
965 nMappedNumType
= 0x90001; // a)
968 nMappedNumType
= 0x00001; // a.
971 case SVX_NUM_ROMAN_UPPER
:
973 if ( sSuffix
== ")" )
975 if ( sPrefix
== "(" )
976 nMappedNumType
= 0xe0001; // (I)
978 nMappedNumType
= 0xf0001; // I)
981 nMappedNumType
= 0x70001; // I.
984 case SVX_NUM_ROMAN_LOWER
:
986 if ( sSuffix
== ")" )
988 if ( sPrefix
== "(" )
989 nMappedNumType
= 0x40001; // (i)
991 nMappedNumType
= 0x50001; // i)
994 nMappedNumType
= 0x60001; // i.
997 case SVX_NUM_ARABIC
:
999 if ( sSuffix
== ")" )
1001 if ( sPrefix
== "(" )
1002 nMappedNumType
= 0xc0001; // (1)
1004 nMappedNumType
= 0x20001; // 1)
1008 if ( sSuffix
.isEmpty() && sPrefix
.isEmpty() )
1009 nMappedNumType
= 0xd0001; // 1
1011 nMappedNumType
= 0x30001; // 1.
1015 case SVX_NUM_NUMBER_UPPER_ZH
:
1017 if ( !sSuffix
.isEmpty() )
1018 nMappedNumType
= 0x110001; // Simplified Chinese with single-byte period.
1020 nMappedNumType
= 0x100001; // Simplified Chinese.
1023 case SVX_NUM_CIRCLE_NUMBER
:
1025 nMappedNumType
= 0x120001; // Double byte circle numbers.
1028 case SVX_NUM_NUMBER_UPPER_ZH_TW
:
1030 if ( !sSuffix
.isEmpty() )
1031 nMappedNumType
= 0x160001; // Traditional Chinese with single-byte period.
1033 nMappedNumType
= 0x150001; // Traditional Chinese.
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.
1043 nMappedNumType
= 0x1A0001; // Japanese/Korean.
1046 case SVX_NUM_FULL_WIDTH_ARABIC
:
1048 if ( !sSuffix
.isEmpty() )
1049 nMappedNumType
= 0x1D0001; // Double-byte Arabic numbers with double-byte period.
1051 nMappedNumType
= 0x1C0001; // Double-byte Arabic numbers.
1060 if ( mbIsBullet
&& bNumberingIsNumber
)
1070 nBulletOfs
= nTextOfs
+ nBulletOfs
;
1071 if ( nBulletOfs
< 0 )
1075 void ParagraphObj::ImplGetParagraphValues( PPTExBulletProvider
* pBuProv
, bool bGetPropStateValue
)
1078 if ( GetPropertyValue( aAny
, mXPropSet
, "NumberingLevel", true ) )
1080 if ( bGetPropStateValue
)
1081 meBullet
= GetPropertyState( mXPropSet
, "NumberingLevel" );
1082 nDepth
= *o3tl::doAccess
<sal_Int16
>(aAny
);
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
:
1113 case css::style::ParagraphAdjust_RIGHT
:
1116 case css::style::ParagraphAdjust_BLOCK
:
1120 case css::style::ParagraphAdjust_LEFT
:
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;
1136 case css::style::LineSpacingMode::MINIMUM
:
1137 case css::style::LineSpacingMode::LEADING
:
1138 mnLineSpacing
= static_cast<sal_Int16
>(-( aLineSpacing
.Height
) );
1139 mbFixedLineSpacing
= false;
1142 case css::style::LineSpacingMode::PROP
:
1144 mnLineSpacing
= static_cast<sal_Int16
>( aLineSpacing
.Height
);
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
;
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
) )
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
)
1240 for ( std::vector
<std::unique_ptr
<PortionObj
> >::iterator it
= mvPortions
.begin(); it
!= mvPortions
.end(); ++it
)
1241 mnTextSize
+= (*it
)->ImplCalculateTextPositions( nCurrentTextPosition
+ mnTextSize
);
1245 ParagraphObj
& ParagraphObj::operator=( const ParagraphObj
& rParagraphObj
)
1247 if ( this != &rParagraphObj
)
1250 ImplConstruct( rParagraphObj
);
1257 sal_uInt32 mnTextSize
;
1259 std::vector
<std::unique_ptr
<ParagraphObj
>> maList
;
1260 bool mbHasExtendedBullets
;
1262 explicit ImplTextObj( int nInstance
);
1265 ImplTextObj::ImplTextObj( int nInstance
)
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() )
1353 FontCollection::~FontCollection()
1355 pVDev
.disposeAndClear();
1356 xPPTBreakIter
= nullptr;
1359 FontCollection::FontCollection() :
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
);
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
)
1384 aFont
.SetCharSet( rEntry
.CharSet
);
1385 aFont
.SetFamilyName( rEntry
.Original
);
1386 aFont
.SetFontHeight( 100 );
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());
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
);
1409 const FontCollectionEntry
* FontCollection::GetById( sal_uInt32 nId
)
1411 return nId
< maFonts
.size() ? &maFonts
[nId
] : nullptr;
1414 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */