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 .
20 #include "drawingml/textparagraphproperties.hxx"
22 #include <com/sun/star/text/XNumberingRulesSupplier.hpp>
23 #include <com/sun/star/container/XIndexReplace.hpp>
24 #include <com/sun/star/text/HoriOrientation.hpp>
25 #include <com/sun/star/awt/FontDescriptor.hpp>
26 #include <com/sun/star/awt/XBitmap.hpp>
27 #include <com/sun/star/graphic/XGraphic.hpp>
28 #include <com/sun/star/beans/PropertyValue.hpp>
29 #include <com/sun/star/style/TabStop.hpp>
30 #include <com/sun/star/text/PositionAndSpaceMode.hpp>
31 #include <com/sun/star/style/ParagraphAdjust.hpp>
33 #include <osl/diagnose.h>
35 #include "oox/helper/helper.hxx"
36 #include "oox/helper/propertyset.hxx"
37 #include "oox/core/xmlfilterbase.hxx"
38 #include "oox/drawingml/drawingmltypes.hxx"
40 #if OSL_DEBUG_LEVEL > 0
41 #include <vcl/unohelp.hxx>
42 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
43 #include <com/sun/star/text/XText.hpp>
44 #include <com/sun/star/drawing/XShape.hpp>
45 #include <comphelper/genericpropertyset.hxx>
46 #include <oox/ppt/pptimport.hxx>
47 #include <oox/ppt/slidepersist.hxx>
50 using namespace ::oox::core
;
51 using namespace ::com::sun::star::uno
;
52 using namespace ::com::sun::star::beans
;
53 using namespace ::com::sun::star::style
;
54 using namespace ::com::sun::star::text
;
55 using namespace ::com::sun::star::container
;
56 using ::com::sun::star::awt::FontDescriptor
;
58 namespace oox
{ namespace drawingml
{
60 BulletList::BulletList( )
61 : maBulletColorPtr( new Color() )
65 bool BulletList::is() const
67 return mnNumberingType
.hasValue();
70 void BulletList::setBulletChar( const OUString
& sChar
)
72 mnNumberingType
<<= NumberingType::CHAR_SPECIAL
;
73 msBulletChar
<<= sChar
;
76 void BulletList::setGraphic( ::com::sun::star::uno::Reference
< ::com::sun::star::graphic::XGraphic
>& rXGraphic
)
78 mnNumberingType
<<= NumberingType::BITMAP
;
79 maGraphic
<<= rXGraphic
;
82 void BulletList::setNone( )
84 mnNumberingType
<<= NumberingType::NUMBER_NONE
;
87 void BulletList::setSuffixParenBoth()
89 msNumberingSuffix
<<= OUString( ")" );
90 msNumberingPrefix
<<= OUString( "(" );
93 void BulletList::setSuffixParenRight()
95 msNumberingSuffix
<<= OUString( ")" );
96 msNumberingPrefix
<<= OUString();
99 void BulletList::setSuffixPeriod()
101 msNumberingSuffix
<<= OUString( "." );
102 msNumberingPrefix
<<= OUString();
105 void BulletList::setSuffixNone()
107 msNumberingSuffix
<<= OUString();
108 msNumberingPrefix
<<= OUString();
111 void BulletList::setSuffixMinusRight()
113 msNumberingSuffix
<<= OUString( "-" );
114 msNumberingPrefix
<<= OUString();
117 void BulletList::setType( sal_Int32 nType
)
119 OSL_ASSERT((nType
& sal_Int32(0xFFFF0000))==0);
120 // OSL_TRACE( "OOX: set list numbering type %d", nType);
123 case XML_alphaLcParenBoth
:
124 mnNumberingType
<<= NumberingType::CHARS_LOWER_LETTER
;
125 setSuffixParenBoth();
127 case XML_alphaLcParenR
:
128 mnNumberingType
<<= NumberingType::CHARS_LOWER_LETTER
;
129 setSuffixParenRight();
131 case XML_alphaLcPeriod
:
132 mnNumberingType
<<= NumberingType::CHARS_LOWER_LETTER
;
135 case XML_alphaUcParenBoth
:
136 mnNumberingType
<<= NumberingType::CHARS_UPPER_LETTER
;
137 setSuffixParenBoth();
139 case XML_alphaUcParenR
:
140 mnNumberingType
<<= NumberingType::CHARS_UPPER_LETTER
;
141 setSuffixParenRight();
143 case XML_alphaUcPeriod
:
144 mnNumberingType
<<= NumberingType::CHARS_UPPER_LETTER
;
147 case XML_arabic1Minus
:
148 case XML_arabic2Minus
:
149 case XML_arabicDbPeriod
:
150 case XML_arabicDbPlain
:
153 case XML_arabicParenBoth
:
154 mnNumberingType
<<= NumberingType::ARABIC
;
155 setSuffixParenBoth();
157 case XML_arabicParenR
:
158 mnNumberingType
<<= NumberingType::ARABIC
;
159 setSuffixParenRight();
161 case XML_arabicPeriod
:
162 mnNumberingType
<<= NumberingType::ARABIC
;
165 case XML_arabicPlain
:
166 mnNumberingType
<<= NumberingType::ARABIC
;
169 case XML_circleNumDbPlain
:
170 case XML_circleNumWdBlackPlain
:
171 case XML_circleNumWdWhitePlain
:
172 mnNumberingType
<<= NumberingType::CIRCLE_NUMBER
;
174 case XML_ea1ChsPeriod
:
175 mnNumberingType
<<= NumberingType::NUMBER_UPPER_ZH
;
178 case XML_ea1ChsPlain
:
179 mnNumberingType
<<= NumberingType::NUMBER_UPPER_ZH
;
182 case XML_ea1ChtPeriod
:
183 mnNumberingType
<<= NumberingType::NUMBER_UPPER_ZH_TW
;
186 case XML_ea1ChtPlain
:
187 mnNumberingType
<<= NumberingType::NUMBER_UPPER_ZH_TW
;
190 case XML_ea1JpnChsDbPeriod
:
191 case XML_ea1JpnKorPeriod
:
192 case XML_ea1JpnKorPlain
:
194 case XML_hebrew2Minus
:
195 mnNumberingType
<<= NumberingType::CHARS_HEBREW
;
196 setSuffixMinusRight();
198 case XML_hindiAlpha1Period
:
199 case XML_hindiAlphaPeriod
:
200 case XML_hindiNumParenR
:
201 case XML_hindiNumPeriod
:
204 case XML_romanLcParenBoth
:
205 mnNumberingType
<<= NumberingType::ROMAN_LOWER
;
206 setSuffixParenBoth();
208 case XML_romanLcParenR
:
209 mnNumberingType
<<= NumberingType::ROMAN_LOWER
;
210 setSuffixParenRight();
212 case XML_romanLcPeriod
:
213 mnNumberingType
<<= NumberingType::ROMAN_LOWER
;
216 case XML_romanUcParenBoth
:
217 mnNumberingType
<<= NumberingType::ROMAN_UPPER
;
218 setSuffixParenBoth();
220 case XML_romanUcParenR
:
221 mnNumberingType
<<= NumberingType::ROMAN_UPPER
;
222 setSuffixParenRight();
224 case XML_romanUcPeriod
:
225 mnNumberingType
<<= NumberingType::ROMAN_UPPER
;
228 case XML_thaiAlphaParenBoth
:
229 case XML_thaiNumParenBoth
:
230 mnNumberingType
<<= NumberingType::CHARS_THAI
;
231 setSuffixParenBoth();
233 case XML_thaiAlphaParenR
:
234 case XML_thaiNumParenR
:
235 mnNumberingType
<<= NumberingType::CHARS_THAI
;
236 setSuffixParenRight();
238 case XML_thaiAlphaPeriod
:
239 case XML_thaiNumPeriod
:
240 mnNumberingType
<<= NumberingType::CHARS_THAI
;
246 void BulletList::setBulletSize(sal_Int16 nSize
)
251 void BulletList::setFontSize(sal_Int16 nSize
)
253 mnFontSize
<<= nSize
;
256 void BulletList::apply( const BulletList
& rSource
)
258 if ( rSource
.maBulletColorPtr
->isUsed() )
259 maBulletColorPtr
= rSource
.maBulletColorPtr
;
260 if ( rSource
.mbBulletColorFollowText
.hasValue() )
261 mbBulletColorFollowText
= rSource
.mbBulletColorFollowText
;
262 if ( rSource
.mbBulletFontFollowText
.hasValue() )
263 mbBulletFontFollowText
= rSource
.mbBulletFontFollowText
;
264 maBulletFont
.assignIfUsed( rSource
.maBulletFont
);
265 if ( rSource
.msBulletChar
.hasValue() )
266 msBulletChar
= rSource
.msBulletChar
;
267 if ( rSource
.mnStartAt
.hasValue() )
268 mnStartAt
= rSource
.mnStartAt
;
269 if ( rSource
.mnNumberingType
.hasValue() )
270 mnNumberingType
= rSource
.mnNumberingType
;
271 if ( rSource
.msNumberingPrefix
.hasValue() )
272 msNumberingPrefix
= rSource
.msNumberingPrefix
;
273 if ( rSource
.msNumberingSuffix
.hasValue() )
274 msNumberingSuffix
= rSource
.msNumberingSuffix
;
275 if ( rSource
.mnSize
.hasValue() )
276 mnSize
= rSource
.mnSize
;
277 if ( rSource
.mnFontSize
.hasValue() )
278 mnFontSize
= rSource
.mnFontSize
;
279 if ( rSource
.maStyleName
.hasValue() )
280 maStyleName
= rSource
.maStyleName
;
281 if ( rSource
.maGraphic
.hasValue() )
282 maGraphic
= rSource
.maGraphic
;
285 void BulletList::pushToPropMap( const ::oox::core::XmlFilterBase
* pFilterBase
, PropertyMap
& rPropMap
) const
287 if( msNumberingPrefix
.hasValue() )
288 rPropMap
.setProperty( PROP_Prefix
, msNumberingPrefix
);
289 if( msNumberingSuffix
.hasValue() )
290 rPropMap
.setProperty( PROP_Suffix
, msNumberingSuffix
);
291 if( mnStartAt
.hasValue() )
292 rPropMap
.setProperty( PROP_StartWith
, mnStartAt
);
293 rPropMap
.setProperty( PROP_Adjust
, HoriOrientation::LEFT
);
295 if( mnNumberingType
.hasValue() )
296 rPropMap
.setProperty( PROP_NumberingType
, mnNumberingType
);
298 OUString aBulletFontName
;
299 sal_Int16 nBulletFontPitch
= 0;
300 sal_Int16 nBulletFontFamily
= 0;
301 bool bSymbolFont
= false;
303 if (maBulletFont
.getFontData( aBulletFontName
, nBulletFontPitch
, nBulletFontFamily
, *pFilterBase
) )
305 FontDescriptor aFontDesc
;
306 sal_Int16 nFontSize
= 0;
307 if( mnFontSize
>>= nFontSize
)
308 aFontDesc
.Height
= nFontSize
;
310 // TODO move the to the TextFont struct.
311 aFontDesc
.Name
= aBulletFontName
;
312 aFontDesc
.Pitch
= nBulletFontPitch
;
313 aFontDesc
.Family
= nBulletFontFamily
;
314 if ( aBulletFontName
.equalsIgnoreAsciiCase("Wingdings") ||
315 aBulletFontName
.equalsIgnoreAsciiCase("Wingdings 2") ||
316 aBulletFontName
.equalsIgnoreAsciiCase("Wingdings 3") ||
317 aBulletFontName
.equalsIgnoreAsciiCase("Monotype Sorts") ||
318 aBulletFontName
.equalsIgnoreAsciiCase("Monotype Sorts 2") ||
319 aBulletFontName
.equalsIgnoreAsciiCase("Webdings") ||
320 aBulletFontName
.equalsIgnoreAsciiCase("StarBats") ||
321 aBulletFontName
.equalsIgnoreAsciiCase("StarMath") ||
322 aBulletFontName
.equalsIgnoreAsciiCase("ZapfDingbats") ) {
323 aFontDesc
.CharSet
= RTL_TEXTENCODING_SYMBOL
;
326 rPropMap
.setProperty( PROP_BulletFont
, aFontDesc
);
327 rPropMap
.setProperty( PROP_BulletFontName
, aBulletFontName
);
330 if ( msBulletChar
.hasValue() ) {
333 msBulletChar
>>= sBuChar
;
335 if( pFilterBase
&& sBuChar
.getLength() == 1 && maBulletFont
.getFontData( aBulletFontName
, nBulletFontPitch
, nBulletFontFamily
, *pFilterBase
) && bSymbolFont
)
337 sal_Unicode nBuChar
= sBuChar
.toChar();
340 sBuChar
= OUString( &nBuChar
, 1 );
343 rPropMap
.setProperty( PROP_BulletChar
, sBuChar
);
345 if ( maGraphic
.hasValue() )
347 Reference
< com::sun::star::awt::XBitmap
> xBitmap( maGraphic
, UNO_QUERY
);
349 rPropMap
.setProperty( PROP_Graphic
, xBitmap
);
351 if( mnSize
.hasValue() )
352 rPropMap
.setProperty( PROP_BulletRelSize
, mnSize
);
353 if ( maStyleName
.hasValue() )
354 rPropMap
.setProperty( PROP_CharStyleName
, maStyleName
);
356 if ( maBulletColorPtr
->isUsed() )
357 rPropMap
.setProperty( PROP_BulletColor
, maBulletColorPtr
->getColor( pFilterBase
->getGraphicHelper() ));
361 TextParagraphProperties::TextParagraphProperties()
366 TextParagraphProperties::~TextParagraphProperties()
370 void TextParagraphProperties::apply( const TextParagraphProperties
& rSourceProps
)
372 maTextParagraphPropertyMap
.assignAll( rSourceProps
.maTextParagraphPropertyMap
);
373 maBulletList
.apply( rSourceProps
.maBulletList
);
374 maTextCharacterProperties
.assignUsed( rSourceProps
.maTextCharacterProperties
);
375 if ( rSourceProps
.maParaTopMargin
.bHasValue
)
376 maParaTopMargin
= rSourceProps
.maParaTopMargin
;
377 if ( rSourceProps
.maParaBottomMargin
.bHasValue
)
378 maParaBottomMargin
= rSourceProps
.maParaBottomMargin
;
379 if ( rSourceProps
.moParaLeftMargin
)
380 moParaLeftMargin
= rSourceProps
.moParaLeftMargin
;
381 if ( rSourceProps
.moFirstLineIndentation
)
382 moFirstLineIndentation
= rSourceProps
.moFirstLineIndentation
;
383 if( rSourceProps
.mnLevel
)
384 mnLevel
= rSourceProps
.mnLevel
;
385 if( rSourceProps
.moParaAdjust
)
386 moParaAdjust
= rSourceProps
.moParaAdjust
;
389 void TextParagraphProperties::pushToPropSet( const ::oox::core::XmlFilterBase
* pFilterBase
,
390 const Reference
< XPropertySet
>& xPropSet
, PropertyMap
& rioBulletMap
, const BulletList
* pMasterBuList
, bool bApplyBulletMap
, float fCharacterSize
,
391 bool bPushDefaultValues
) const
393 PropertySet
aPropSet( xPropSet
);
394 aPropSet
.setProperties( maTextParagraphPropertyMap
);
396 sal_Int32 nNumberingType
= NumberingType::NUMBER_NONE
;
397 if ( maBulletList
.mnNumberingType
.hasValue() )
398 maBulletList
.mnNumberingType
>>= nNumberingType
;
399 else if ( pMasterBuList
&& pMasterBuList
->mnNumberingType
.hasValue() )
400 pMasterBuList
->mnNumberingType
>>= nNumberingType
;
401 if ( nNumberingType
== NumberingType::NUMBER_NONE
)
402 aPropSet
.setProperty
< sal_Int16
>( PROP_NumberingLevel
, -1 );
404 maBulletList
.pushToPropMap( pFilterBase
, rioBulletMap
);
406 if ( maParaTopMargin
.bHasValue
|| bPushDefaultValues
)
407 aPropSet
.setProperty( PROP_ParaTopMargin
, maParaTopMargin
.toMargin( fCharacterSize
!= 0.0 ? fCharacterSize
: getCharHeightPoints ( 12.0 ) ) );
408 if ( maParaBottomMargin
.bHasValue
|| bPushDefaultValues
)
409 aPropSet
.setProperty( PROP_ParaBottomMargin
, maParaBottomMargin
.toMargin( fCharacterSize
!= 0.0 ? fCharacterSize
: getCharHeightPoints ( 12.0 ) ) );
410 if ( nNumberingType
== NumberingType::BITMAP
)
412 fCharacterSize
= getCharHeightPoints( fCharacterSize
);
414 com::sun::star::awt::Size aBulletSize
;
415 aBulletSize
.Width
= aBulletSize
.Height
= static_cast< sal_Int32
>( ( fCharacterSize
* ( 2540.0 / 72.0 ) * 0.8 ) );
416 rioBulletMap
.setProperty( PROP_GraphicSize
, aBulletSize
);
419 boost::optional
< sal_Int32
> noParaLeftMargin( moParaLeftMargin
);
420 boost::optional
< sal_Int32
> noFirstLineIndentation( moFirstLineIndentation
);
422 if ( nNumberingType
!= NumberingType::NUMBER_NONE
)
424 if ( noParaLeftMargin
)
426 aPropSet
.setProperty( PROP_ParaLeftMargin
, static_cast< sal_Int32
>(0));
427 rioBulletMap
.setProperty( PROP_LeftMargin
, static_cast< sal_Int32
>( *noParaLeftMargin
));
428 noParaLeftMargin
= boost::none
;
430 if ( noFirstLineIndentation
)
432 // Force Paragraph property as zero - impress seems to use the value from previous
433 // (non) bullet line if not set to zero explicitly :(
434 aPropSet
.setProperty( PROP_ParaFirstLineIndent
, static_cast< sal_Int32
>(0) );
435 rioBulletMap
.setProperty( PROP_FirstLineOffset
, static_cast< sal_Int32
>( *noFirstLineIndentation
));
436 noFirstLineIndentation
= boost::none
;
438 if ( nNumberingType
!= NumberingType::BITMAP
&& !rioBulletMap
.hasProperty( PROP_BulletColor
) && pFilterBase
)
439 rioBulletMap
.setProperty( PROP_BulletColor
, static_cast< sal_Int32
>( maTextCharacterProperties
.maCharColor
.getColor( pFilterBase
->getGraphicHelper())));
442 if ( bApplyBulletMap
)
444 Reference
< XIndexReplace
> xNumRule
;
445 aPropSet
.getProperty( xNumRule
, PROP_NumberingRules
);
446 OSL_ENSURE( xNumRule
.is(), "can't get Numbering rules");
452 if( !rioBulletMap
.empty() )
454 // fix default bullet size to be 100%
455 if( !rioBulletMap
.hasProperty( PROP_BulletRelSize
) )
456 rioBulletMap
.setProperty( PROP_BulletRelSize
, static_cast< sal_Int16
>( 100 ));
457 Sequence
< PropertyValue
> aBulletPropSeq
= rioBulletMap
.makePropertyValueSequence();
458 xNumRule
->replaceByIndex( getLevel(), makeAny( aBulletPropSeq
) );
461 aPropSet
.setProperty( PROP_NumberingRules
, xNumRule
);
464 catch (const Exception
&)
466 // Don't warn for now, expected to fail for Writer.
469 if ( noParaLeftMargin
)
470 aPropSet
.setProperty( PROP_ParaLeftMargin
, sal_Int32( *noParaLeftMargin
) );
471 if ( noFirstLineIndentation
)
473 aPropSet
.setProperty( PROP_ParaFirstLineIndent
, *noFirstLineIndentation
);
474 if( bPushDefaultValues
)
476 // Reset TabStops - these would be auto calculated by Impress
478 aTabStop
.Position
= 0;
479 Sequence
< TabStop
> aSeq(1);
481 aPropSet
.setProperty( PROP_ParaTabStops
, aSeq
);
487 aPropSet
.setProperty( PROP_ParaAdjust
, moParaAdjust
.get());
491 aPropSet
.setProperty( PROP_ParaAdjust
, com::sun::star::style::ParagraphAdjust_LEFT
);
495 float TextParagraphProperties::getCharHeightPoints( float fDefault
) const
497 return maTextCharacterProperties
.getCharHeightPoints( fDefault
);
501 // Note: Please don't remove this function. This is required for
502 // debugging pptx import problems.
503 void TextParagraphProperties::dump() const
505 Reference
< ::com::sun::star::drawing::XShape
> xShape( oox::ppt::PowerPointImport::mpDebugFilterBase
->getModelFactory()->createInstance( "com.sun.star.presentation.TitleTextShape" ), UNO_QUERY
);
506 Reference
< ::com::sun::star::text::XText
> xText( xShape
, UNO_QUERY
);
508 Reference
< com::sun::star::drawing::XDrawPage
> xDebugPage(ppt::SlidePersist::mxDebugPage
.get(), UNO_QUERY
);
510 xDebugPage
->add( xShape
);
512 PropertyMap emptyMap
;
514 const OUString sText
= "debug";
515 xText
->setString( sText
);
516 Reference
< ::com::sun::star::text::XTextCursor
> xStart( xText
->createTextCursor(), UNO_QUERY
);
517 Reference
< ::com::sun::star::text::XTextRange
> xRange( xStart
, UNO_QUERY
);
518 xStart
->gotoEnd( sal_True
);
519 Reference
< XPropertySet
> xPropSet( xRange
, UNO_QUERY
);
520 pushToPropSet( NULL
, xPropSet
, emptyMap
, NULL
, false, 0 );
521 PropertySet
pSet( xPropSet
);
527 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */