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 if ( aPropertySequence
->hasElements() )
799 bExtendedParameters
= true;
800 nBulletRealSize
= 100;
803 uno::Reference
<graphic::XGraphic
> xGraphic
;
804 for ( const css::beans::PropertyValue
& rPropValue
: *aPropertySequence
)
806 OUString
aPropName( rPropValue
.Name
);
807 if ( aPropName
== "NumberingType" )
808 nNumberingType
= static_cast<SvxNumType
>(*o3tl::doAccess
<sal_Int16
>(rPropValue
.Value
));
809 else if ( aPropName
== "Adjust" )
810 nHorzAdjust
= *o3tl::doAccess
<sal_Int16
>(rPropValue
.Value
);
811 else if ( aPropName
== "BulletChar" )
813 OUString
aString( *o3tl::doAccess
<OUString
>(rPropValue
.Value
) );
814 if ( !aString
.isEmpty() )
815 cBulletId
= aString
[ 0 ];
817 else if ( aPropName
== "BulletFont" )
819 aFontDesc
= *o3tl::doAccess
<css::awt::FontDescriptor
>(rPropValue
.Value
);
821 // Our numbullet dialog has set the wrong textencoding for our "StarSymbol" font,
822 // instead of a Unicode encoding the encoding RTL_TEXTENCODING_SYMBOL was used.
823 // Because there might exist a lot of damaged documemts I added this two lines
824 // which fixes the bullet problem for the export.
825 if ( aFontDesc
.Name
.equalsIgnoreAsciiCase("StarSymbol") )
826 aFontDesc
.CharSet
= RTL_TEXTENCODING_MS_1252
;
829 else if ( aPropName
== "GraphicBitmap" )
831 auto xBitmap
= rPropValue
.Value
.get
<uno::Reference
<awt::XBitmap
>>();
832 xGraphic
.set(xBitmap
, uno::UNO_QUERY
);
834 else if ( aPropName
== "GraphicSize" )
836 if (auto aSize
= o3tl::tryAccess
<css::awt::Size
>(rPropValue
.Value
))
838 // don't cast awt::Size to Size as on 64-bits they are not the same.
839 aBuGraSize
.setWidth( aSize
->Width
);
840 aBuGraSize
.setHeight( aSize
->Height
);
843 else if ( aPropName
== "StartWith" )
844 nStartWith
= *o3tl::doAccess
<sal_Int16
>(rPropValue
.Value
);
845 else if ( aPropName
== "LeftMargin" )
846 nTextOfs
= nTextOfs
+ static_cast< sal_Int16
>( *o3tl::doAccess
<sal_Int32
>(rPropValue
.Value
) / ( 2540.0 / 576 ) );
847 else if ( aPropName
== "FirstLineOffset" )
848 nBulletOfs
+= static_cast<sal_Int16
>( *o3tl::doAccess
<sal_Int32
>(rPropValue
.Value
) / ( 2540.0 / 576 ) );
849 else if ( aPropName
== "BulletColor" )
851 sal_uInt32 nSOColor
= *o3tl::doAccess
<sal_uInt32
>(rPropValue
.Value
);
852 nBulletColor
= nSOColor
& 0xff00ff00; // green and hibyte
853 nBulletColor
|= static_cast<sal_uInt8
>(nSOColor
) << 16; // red
854 nBulletColor
|= static_cast<sal_uInt8
>( nSOColor
>> 16 ) | 0xfe000000; // blue
856 else if ( aPropName
== "BulletRelSize" )
858 nBulletRealSize
= *o3tl::doAccess
<sal_Int16
>(rPropValue
.Value
);
862 else if ( aPropName
== "Prefix" )
863 sPrefix
= *o3tl::doAccess
<OUString
>(rPropValue
.Value
);
864 else if ( aPropName
== "Suffix" )
865 sSuffix
= *o3tl::doAccess
<OUString
>(rPropValue
.Value
);
868 ( aPropName
== "SymbolTextDistance" )
869 || ( aPropName
== "GraphicBitmap" ) ) )
871 OSL_FAIL( "Unknown Property" );
878 if ( aBuGraSize
.Width() && aBuGraSize
.Height() )
880 Graphic
aGraphic(xGraphic
);
881 nBulletId
= pBuProv
->GetId(xGraphic
, aBuGraSize
);
882 if ( nBulletId
!= 0xffff )
883 bExtendedBulletsUsed
= true;
887 nNumberingType
= SVX_NUM_NUMBER_NONE
;
891 CalculateGraphicBulletSize( ( mvPortions
.empty() ) ? 24 : mvPortions
.front()->mnCharHeight
);
893 switch( nNumberingType
)
895 case SVX_NUM_NUMBER_NONE
: nParaFlags
|= 0xf; break;
897 case SVX_NUM_CHAR_SPECIAL
: // Bullet
899 if ( IsStarSymbol(aFontDesc
.Name
) )
901 rtl_TextEncoding eChrSet
= aFontDesc
.CharSet
;
902 cBulletId
= msfilter::util::bestFitOpenSymbolToMSFont(cBulletId
, eChrSet
, aFontDesc
.Name
);
903 aFontDesc
.CharSet
= eChrSet
;
906 if ( !aFontDesc
.Name
.isEmpty() )
908 nParaFlags
|= 0x90; // we define the font and charset
913 case SVX_NUM_CHARS_UPPER_LETTER
: // count from a-z, aa - az, ba - bz, ...
914 case SVX_NUM_CHARS_LOWER_LETTER
:
915 case SVX_NUM_ROMAN_UPPER
:
916 case SVX_NUM_ROMAN_LOWER
:
917 case SVX_NUM_ARABIC
:
918 case SVX_NUM_PAGEDESC
: // numbering from the page template
919 case SVX_NUM_BITMAP
:
920 case SVX_NUM_CHARS_UPPER_LETTER_N
: // count from a-z, aa-zz, aaa-zzz
921 case SVX_NUM_CHARS_LOWER_LETTER_N
:
922 case SVX_NUM_NUMBER_UPPER_ZH
:
923 case SVX_NUM_CIRCLE_NUMBER
:
924 case SVX_NUM_NUMBER_UPPER_ZH_TW
:
925 case SVX_NUM_NUMBER_LOWER_ZH
:
926 case SVX_NUM_FULL_WIDTH_ARABIC
:
928 if ( nNumberingType
!= SVX_NUM_CHAR_SPECIAL
)
930 bExtendedBulletsUsed
= true;
931 if ( nNumberingDepth
& 1 )
932 cBulletId
= 0x2013; // defaulting bullet characters for ppt97
933 else if ( nNumberingDepth
== 4 )
938 switch( nNumberingType
)
940 case SVX_NUM_CHARS_UPPER_LETTER
:
941 case SVX_NUM_CHARS_UPPER_LETTER_N
:
943 if ( sSuffix
== ")" )
945 if ( sPrefix
== "(" )
946 nMappedNumType
= 0xa0001; // (A)
948 nMappedNumType
= 0xb0001; // A)
951 nMappedNumType
= 0x10001; // A.
954 case SVX_NUM_CHARS_LOWER_LETTER
:
955 case SVX_NUM_CHARS_LOWER_LETTER_N
:
957 if ( sSuffix
== ")" )
959 if ( sPrefix
== "(" )
960 nMappedNumType
= 0x80001; // (a)
962 nMappedNumType
= 0x90001; // a)
965 nMappedNumType
= 0x00001; // a.
968 case SVX_NUM_ROMAN_UPPER
:
970 if ( sSuffix
== ")" )
972 if ( sPrefix
== "(" )
973 nMappedNumType
= 0xe0001; // (I)
975 nMappedNumType
= 0xf0001; // I)
978 nMappedNumType
= 0x70001; // I.
981 case SVX_NUM_ROMAN_LOWER
:
983 if ( sSuffix
== ")" )
985 if ( sPrefix
== "(" )
986 nMappedNumType
= 0x40001; // (i)
988 nMappedNumType
= 0x50001; // i)
991 nMappedNumType
= 0x60001; // i.
994 case SVX_NUM_ARABIC
:
996 if ( sSuffix
== ")" )
998 if ( sPrefix
== "(" )
999 nMappedNumType
= 0xc0001; // (1)
1001 nMappedNumType
= 0x20001; // 1)
1005 if ( sSuffix
.isEmpty() && sPrefix
.isEmpty() )
1006 nMappedNumType
= 0xd0001; // 1
1008 nMappedNumType
= 0x30001; // 1.
1012 case SVX_NUM_NUMBER_UPPER_ZH
:
1014 if ( !sSuffix
.isEmpty() )
1015 nMappedNumType
= 0x110001; // Simplified Chinese with single-byte period.
1017 nMappedNumType
= 0x100001; // Simplified Chinese.
1020 case SVX_NUM_CIRCLE_NUMBER
:
1022 nMappedNumType
= 0x120001; // Double byte circle numbers.
1025 case SVX_NUM_NUMBER_UPPER_ZH_TW
:
1027 if ( !sSuffix
.isEmpty() )
1028 nMappedNumType
= 0x160001; // Traditional Chinese with single-byte period.
1030 nMappedNumType
= 0x150001; // Traditional Chinese.
1033 case SVX_NUM_NUMBER_LOWER_ZH
:
1035 if ( sSuffix
== u
"\uff0e" )
1036 nMappedNumType
= 0x260001; // Japanese with double-byte period.
1037 else if ( !sSuffix
.isEmpty() )
1038 nMappedNumType
= 0x1B0001; // Japanese/Korean with single-byte period.
1040 nMappedNumType
= 0x1A0001; // Japanese/Korean.
1043 case SVX_NUM_FULL_WIDTH_ARABIC
:
1045 if ( !sSuffix
.isEmpty() )
1046 nMappedNumType
= 0x1D0001; // Double-byte Arabic numbers with double-byte period.
1048 nMappedNumType
= 0x1C0001; // Double-byte Arabic numbers.
1057 if ( mbIsBullet
&& bNumberingIsNumber
)
1067 nBulletOfs
= nTextOfs
+ nBulletOfs
;
1068 if ( nBulletOfs
< 0 )
1072 void ParagraphObj::ImplGetParagraphValues( PPTExBulletProvider
* pBuProv
, bool bGetPropStateValue
)
1075 if ( GetPropertyValue( aAny
, mXPropSet
, "NumberingLevel", true ) )
1077 if ( bGetPropStateValue
)
1078 meBullet
= GetPropertyState( mXPropSet
, "NumberingLevel" );
1079 nDepth
= *o3tl::doAccess
<sal_Int16
>(aAny
);
1098 ImplGetNumberingLevel( pBuProv
, nDepth
, mbIsBullet
, bGetPropStateValue
);
1100 if ( ImplGetPropertyValue( "ParaTabStops", bGetPropStateValue
) )
1101 maTabStop
= *o3tl::doAccess
<css::uno::Sequence
<css::style::TabStop
>>(mAny
);
1102 sal_Int16 eTextAdjust
= sal_Int16(css::style::ParagraphAdjust_LEFT
);
1103 if ( GetPropertyValue( aAny
, mXPropSet
, "ParaAdjust", bGetPropStateValue
) )
1104 aAny
>>= eTextAdjust
;
1105 switch ( static_cast<css::style::ParagraphAdjust
>(eTextAdjust
) )
1107 case css::style::ParagraphAdjust_CENTER
:
1110 case css::style::ParagraphAdjust_RIGHT
:
1113 case css::style::ParagraphAdjust_BLOCK
:
1117 case css::style::ParagraphAdjust_LEFT
:
1121 meTextAdjust
= ePropState
;
1123 if ( ImplGetPropertyValue( "ParaLineSpacing", bGetPropStateValue
) )
1125 css::style::LineSpacing aLineSpacing
1126 = *o3tl::doAccess
<css::style::LineSpacing
>(mAny
);
1127 switch ( aLineSpacing
.Mode
)
1129 case css::style::LineSpacingMode::FIX
:
1130 mnLineSpacing
= static_cast<sal_Int16
>(-( aLineSpacing
.Height
) );
1131 mbFixedLineSpacing
= true;
1133 case css::style::LineSpacingMode::MINIMUM
:
1134 case css::style::LineSpacingMode::LEADING
:
1135 mnLineSpacing
= static_cast<sal_Int16
>(-( aLineSpacing
.Height
) );
1136 mbFixedLineSpacing
= false;
1139 case css::style::LineSpacingMode::PROP
:
1141 mnLineSpacing
= static_cast<sal_Int16
>( aLineSpacing
.Height
);
1145 meLineSpacing
= ePropState
;
1147 if ( ImplGetPropertyValue( "ParaBottomMargin", bGetPropStateValue
) )
1149 double fSpacing
= *o3tl::doAccess
<sal_uInt32
>(mAny
) + ( 2540.0 / 576.0 ) - 1;
1150 mnLineSpacingBottom
= static_cast<sal_Int16
>(-( fSpacing
* 576.0 / 2540.0 ) );
1152 meLineSpacingBottom
= ePropState
;
1154 if ( ImplGetPropertyValue( "ParaTopMargin", bGetPropStateValue
) )
1156 double fSpacing
= *o3tl::doAccess
<sal_uInt32
>(mAny
) + ( 2540.0 / 576.0 ) - 1;
1157 mnLineSpacingTop
= static_cast<sal_Int16
>(-( fSpacing
* 576.0 / 2540.0 ) );
1159 meLineSpacingTop
= ePropState
;
1161 if ( ImplGetPropertyValue( "ParaIsForbiddenRules", bGetPropStateValue
) )
1162 mAny
>>= mbForbiddenRules
;
1163 meForbiddenRules
= ePropState
;
1165 if ( ImplGetPropertyValue( "ParaIsHangingPunctuation", bGetPropStateValue
) )
1166 mAny
>>= mbParagraphPunctation
;
1167 meParagraphPunctation
= ePropState
;
1170 if ( ImplGetPropertyValue( "WritingMode", bGetPropStateValue
) )
1172 sal_Int16 nWritingMode
= 0;
1173 mAny
>>= nWritingMode
;
1175 SvxFrameDirection eWritingMode
= static_cast<SvxFrameDirection
>(nWritingMode
);
1176 if ( ( eWritingMode
== SvxFrameDirection::Horizontal_RL_TB
)
1177 || ( eWritingMode
== SvxFrameDirection::Vertical_RL_TB
) )
1182 meBiDi
= ePropState
;
1185 void ParagraphObj::ImplConstruct( const ParagraphObj
& rParagraphObj
)
1187 mbIsBullet
= rParagraphObj
.mbIsBullet
;
1188 meBullet
= rParagraphObj
.meBullet
;
1189 meTextAdjust
= rParagraphObj
.meTextAdjust
;
1190 meLineSpacing
= rParagraphObj
.meLineSpacing
;
1191 meLineSpacingTop
= rParagraphObj
.meLineSpacingTop
;
1192 meLineSpacingBottom
= rParagraphObj
.meLineSpacingBottom
;
1193 meForbiddenRules
= rParagraphObj
.meForbiddenRules
;
1194 meParagraphPunctation
= rParagraphObj
.meParagraphPunctation
;
1195 meBiDi
=rParagraphObj
.meBiDi
;
1196 mbFixedLineSpacing
= rParagraphObj
.mbFixedLineSpacing
;
1197 mnTextSize
= rParagraphObj
.mnTextSize
;
1198 mnTextAdjust
= rParagraphObj
.mnTextAdjust
;
1199 mnLineSpacing
= rParagraphObj
.mnLineSpacing
;
1200 mnLineSpacingTop
= rParagraphObj
.mnLineSpacingTop
;
1201 mnLineSpacingBottom
= rParagraphObj
.mnLineSpacingBottom
;
1202 mbFirstParagraph
= rParagraphObj
.mbFirstParagraph
;
1203 mbLastParagraph
= rParagraphObj
.mbLastParagraph
;
1204 mbParagraphPunctation
= rParagraphObj
.mbParagraphPunctation
;
1205 mbForbiddenRules
= rParagraphObj
.mbForbiddenRules
;
1206 mnBiDi
= rParagraphObj
.mnBiDi
;
1208 for ( std::vector
<std::unique_ptr
<PortionObj
> >::const_iterator it
= rParagraphObj
.begin(); it
!= rParagraphObj
.end(); ++it
)
1209 mvPortions
.push_back( std::make_unique
<PortionObj
>( **it
) );
1211 maTabStop
= rParagraphObj
.maTabStop
;
1212 bExtendedParameters
= rParagraphObj
.bExtendedParameters
;
1213 nParaFlags
= rParagraphObj
.nParaFlags
;
1214 nBulletFlags
= rParagraphObj
.nBulletFlags
;
1215 sPrefix
= rParagraphObj
.sPrefix
;
1216 sSuffix
= rParagraphObj
.sSuffix
;
1217 sGraphicUrl
= rParagraphObj
.sGraphicUrl
; // String to a graphic
1218 aBuGraSize
= rParagraphObj
.aBuGraSize
;
1219 nNumberingType
= rParagraphObj
.nNumberingType
; // this is actually a SvxEnum
1220 nHorzAdjust
= rParagraphObj
.nHorzAdjust
;
1221 nBulletColor
= rParagraphObj
.nBulletColor
;
1222 nBulletOfs
= rParagraphObj
.nBulletOfs
;
1223 nStartWith
= rParagraphObj
.nStartWith
; // start of numbering
1224 nTextOfs
= rParagraphObj
.nTextOfs
;
1225 nBulletRealSize
= rParagraphObj
.nBulletRealSize
; // scale in percent
1226 nDepth
= rParagraphObj
.nDepth
; // actual depth
1227 cBulletId
= rParagraphObj
.cBulletId
; // if Numbering Type == CharSpecial
1228 aFontDesc
= rParagraphObj
.aFontDesc
;
1230 bExtendedBulletsUsed
= rParagraphObj
.bExtendedBulletsUsed
;
1231 nBulletId
= rParagraphObj
.nBulletId
;
1234 sal_uInt32
ParagraphObj::ImplCalculateTextPositions( sal_uInt32 nCurrentTextPosition
)
1237 for ( std::vector
<std::unique_ptr
<PortionObj
> >::iterator it
= mvPortions
.begin(); it
!= mvPortions
.end(); ++it
)
1238 mnTextSize
+= (*it
)->ImplCalculateTextPositions( nCurrentTextPosition
+ mnTextSize
);
1242 ParagraphObj
& ParagraphObj::operator=( const ParagraphObj
& rParagraphObj
)
1244 if ( this != &rParagraphObj
)
1247 ImplConstruct( rParagraphObj
);
1254 sal_uInt32 mnTextSize
;
1256 std::vector
<std::unique_ptr
<ParagraphObj
>> maList
;
1257 bool mbHasExtendedBullets
;
1259 explicit ImplTextObj( int nInstance
);
1262 ImplTextObj::ImplTextObj( int nInstance
)
1266 mnInstance
= nInstance
;
1267 mbHasExtendedBullets
= false;
1270 TextObj::TextObj( css::uno::Reference
< css::text::XSimpleText
> const & rXTextRef
,
1271 int nInstance
, FontCollection
& rFontCollection
, PPTExBulletProvider
& rProv
):
1272 mpImplTextObj(new ImplTextObj(nInstance
))
1274 css::uno::Reference
< css::container::XEnumerationAccess
> aXTextParagraphEA( rXTextRef
, css::uno::UNO_QUERY
);
1276 if ( aXTextParagraphEA
.is() )
1278 css::uno::Reference
< css::container::XEnumeration
> aXTextParagraphE( aXTextParagraphEA
->createEnumeration() );
1279 if ( aXTextParagraphE
.is() )
1281 ParaFlags aParaFlags
;
1282 while ( aXTextParagraphE
->hasMoreElements() )
1284 css::uno::Reference
< css::text::XTextContent
> aXParagraph
;
1285 css::uno::Any
aAny( aXTextParagraphE
->nextElement() );
1286 if ( aAny
>>= aXParagraph
)
1288 if ( !aXTextParagraphE
->hasMoreElements() )
1289 aParaFlags
.bLastParagraph
= true;
1290 std::unique_ptr
<ParagraphObj
> pPara(new ParagraphObj( aXParagraph
, aParaFlags
, rFontCollection
, rProv
));
1291 mpImplTextObj
->mbHasExtendedBullets
|= pPara
->bExtendedBulletsUsed
;
1292 mpImplTextObj
->maList
.push_back( std::move(pPara
) );
1293 aParaFlags
.bFirstParagraph
= false;
1298 ImplCalculateTextPositions();
1301 void TextObj::ImplCalculateTextPositions()
1303 mpImplTextObj
->mnTextSize
= 0;
1304 for ( sal_uInt32 i
= 0; i
< ParagraphCount(); ++i
)
1305 mpImplTextObj
->mnTextSize
+= GetParagraph(i
)->ImplCalculateTextPositions( mpImplTextObj
->mnTextSize
);
1308 ParagraphObj
* TextObj::GetParagraph(int idx
)
1310 return mpImplTextObj
->maList
[idx
].get();
1313 sal_uInt32
TextObj::ParagraphCount() const
1315 return mpImplTextObj
->maList
.size();
1318 sal_uInt32
TextObj::Count() const
1320 return mpImplTextObj
->mnTextSize
;
1323 int TextObj::GetInstance() const
1325 return mpImplTextObj
->mnInstance
;
1328 bool TextObj::HasExtendedBullets() const
1330 return mpImplTextObj
->mbHasExtendedBullets
;
1333 FontCollectionEntry::~FontCollectionEntry()
1337 void FontCollectionEntry::ImplInit( const OUString
& rName
)
1339 OUString
aSubstName( GetSubsFontName( rName
, SubsFontFlags::ONLYONE
| SubsFontFlags::MS
) );
1340 if ( !aSubstName
.isEmpty() )
1350 FontCollection::~FontCollection()
1352 pVDev
.disposeAndClear();
1353 xPPTBreakIter
= nullptr;
1356 FontCollection::FontCollection() :
1359 xPPTBreakIter
= css::i18n::BreakIterator::create( ::comphelper::getProcessComponentContext() );
1362 short FontCollection::GetScriptDirection( const OUString
& rString
)
1364 short nRet
= ScriptTypeDetector::getScriptDirection( rString
, 0, css::i18n::ScriptDirection::NEUTRAL
);
1368 sal_uInt32
FontCollection::GetId( FontCollectionEntry
& rEntry
)
1370 if( !rEntry
.Name
.isEmpty() )
1372 const sal_uInt32 nFonts
= maFonts
.size();
1374 for( sal_uInt32 i
= 0; i
< nFonts
; i
++ )
1376 const FontCollectionEntry
* pEntry
= GetById( i
);
1377 if( pEntry
->Name
== rEntry
.Name
)
1381 aFont
.SetCharSet( rEntry
.CharSet
);
1382 aFont
.SetFamilyName( rEntry
.Original
);
1383 aFont
.SetFontHeight( 100 );
1386 pVDev
= VclPtr
<VirtualDevice
>::Create();
1388 pVDev
->SetFont( aFont
);
1389 FontMetric
aMetric( pVDev
->GetFontMetric() );
1391 sal_uInt16 nTxtHeight
= static_cast<sal_uInt16
>(aMetric
.GetAscent()) + static_cast<sal_uInt16
>(aMetric
.GetDescent());
1395 double fScaling
= static_cast<double>(nTxtHeight
) / 120.0;
1396 if ( ( fScaling
> 0.50 ) && ( fScaling
< 1.5 ) )
1397 rEntry
.Scaling
= fScaling
;
1400 maFonts
.push_back(rEntry
);
1406 const FontCollectionEntry
* FontCollection::GetById( sal_uInt32 nId
)
1408 return nId
< maFonts
.size() ? &maFonts
[nId
] : nullptr;
1411 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */