Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / oox / source / drawingml / textparagraphproperties.cxx
blob0a825cfc28c1a2c5bec03584435013619537e645
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "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>
32 #include <com/sun/star/drawing/XDrawPage.hpp>
34 #include <osl/diagnose.h>
36 #include "oox/helper/helper.hxx"
37 #include "oox/helper/propertyset.hxx"
38 #include "oox/core/xmlfilterbase.hxx"
39 #include "oox/drawingml/drawingmltypes.hxx"
40 #include <oox/token/properties.hxx>
41 #include <oox/token/tokens.hxx>
43 #if OSL_DEBUG_LEVEL > 0
44 #include <vcl/unohelp.hxx>
45 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
46 #include <com/sun/star/text/XText.hpp>
47 #include <com/sun/star/drawing/XShape.hpp>
48 #include <comphelper/genericpropertyset.hxx>
49 #include <oox/ppt/pptimport.hxx>
50 #include <oox/ppt/slidepersist.hxx>
51 #endif
53 using namespace ::oox::core;
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::beans;
56 using namespace ::com::sun::star::style;
57 using namespace ::com::sun::star::text;
58 using namespace ::com::sun::star::container;
59 using ::com::sun::star::awt::FontDescriptor;
61 namespace oox { namespace drawingml {
63 BulletList::BulletList( )
64 : maBulletColorPtr( new Color() )
68 bool BulletList::is() const
70 return mnNumberingType.hasValue();
73 void BulletList::setBulletChar( const OUString & sChar )
75 mnNumberingType <<= NumberingType::CHAR_SPECIAL;
76 msBulletChar <<= sChar;
79 void BulletList::setGraphic( css::uno::Reference< css::graphic::XGraphic >& rXGraphic )
81 mnNumberingType <<= NumberingType::BITMAP;
82 maGraphic <<= rXGraphic;
85 void BulletList::setNone( )
87 mnNumberingType <<= NumberingType::NUMBER_NONE;
90 void BulletList::setSuffixParenBoth()
92 msNumberingSuffix <<= OUString( ")" );
93 msNumberingPrefix <<= OUString( "(" );
96 void BulletList::setSuffixParenRight()
98 msNumberingSuffix <<= OUString( ")" );
99 msNumberingPrefix <<= OUString();
102 void BulletList::setSuffixPeriod()
104 msNumberingSuffix <<= OUString( "." );
105 msNumberingPrefix <<= OUString();
108 void BulletList::setSuffixNone()
110 msNumberingSuffix <<= OUString();
111 msNumberingPrefix <<= OUString();
114 void BulletList::setSuffixMinusRight()
116 msNumberingSuffix <<= OUString( "-" );
117 msNumberingPrefix <<= OUString();
120 void BulletList::setType( sal_Int32 nType )
122 OSL_ASSERT((nType & sal_Int32(0xFFFF0000))==0);
123 switch( nType )
125 case XML_alphaLcParenBoth:
126 mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER;
127 setSuffixParenBoth();
128 break;
129 case XML_alphaLcParenR:
130 mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER;
131 setSuffixParenRight();
132 break;
133 case XML_alphaLcPeriod:
134 mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER;
135 setSuffixPeriod();
136 break;
137 case XML_alphaUcParenBoth:
138 mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER;
139 setSuffixParenBoth();
140 break;
141 case XML_alphaUcParenR:
142 mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER;
143 setSuffixParenRight();
144 break;
145 case XML_alphaUcPeriod:
146 mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER;
147 setSuffixPeriod();
148 break;
149 case XML_arabic1Minus:
150 case XML_arabic2Minus:
151 case XML_arabicDbPeriod:
152 case XML_arabicDbPlain:
153 // TODO
154 break;
155 case XML_arabicParenBoth:
156 mnNumberingType <<= NumberingType::ARABIC;
157 setSuffixParenBoth();
158 break;
159 case XML_arabicParenR:
160 mnNumberingType <<= NumberingType::ARABIC;
161 setSuffixParenRight();
162 break;
163 case XML_arabicPeriod:
164 mnNumberingType <<= NumberingType::ARABIC;
165 setSuffixPeriod();
166 break;
167 case XML_arabicPlain:
168 mnNumberingType <<= NumberingType::ARABIC;
169 setSuffixNone();
170 break;
171 case XML_circleNumDbPlain:
172 case XML_circleNumWdBlackPlain:
173 case XML_circleNumWdWhitePlain:
174 mnNumberingType <<= NumberingType::CIRCLE_NUMBER;
175 break;
176 case XML_ea1ChsPeriod:
177 mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH;
178 setSuffixPeriod();
179 break;
180 case XML_ea1ChsPlain:
181 mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH;
182 setSuffixNone();
183 break;
184 case XML_ea1ChtPeriod:
185 mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH_TW;
186 setSuffixPeriod();
187 break;
188 case XML_ea1ChtPlain:
189 mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH_TW;
190 setSuffixNone();
191 break;
192 case XML_ea1JpnChsDbPeriod:
193 case XML_ea1JpnKorPeriod:
194 case XML_ea1JpnKorPlain:
195 break;
196 case XML_hebrew2Minus:
197 mnNumberingType <<= NumberingType::CHARS_HEBREW;
198 setSuffixMinusRight();
199 break;
200 case XML_hindiAlpha1Period:
201 case XML_hindiAlphaPeriod:
202 case XML_hindiNumParenR:
203 case XML_hindiNumPeriod:
204 // TODO
205 break;
206 case XML_romanLcParenBoth:
207 mnNumberingType <<= NumberingType::ROMAN_LOWER;
208 setSuffixParenBoth();
209 break;
210 case XML_romanLcParenR:
211 mnNumberingType <<= NumberingType::ROMAN_LOWER;
212 setSuffixParenRight();
213 break;
214 case XML_romanLcPeriod:
215 mnNumberingType <<= NumberingType::ROMAN_LOWER;
216 setSuffixPeriod();
217 break;
218 case XML_romanUcParenBoth:
219 mnNumberingType <<= NumberingType::ROMAN_UPPER;
220 setSuffixParenBoth();
221 break;
222 case XML_romanUcParenR:
223 mnNumberingType <<= NumberingType::ROMAN_UPPER;
224 setSuffixParenRight();
225 break;
226 case XML_romanUcPeriod:
227 mnNumberingType <<= NumberingType::ROMAN_UPPER;
228 setSuffixPeriod();
229 break;
230 case XML_thaiAlphaParenBoth:
231 case XML_thaiNumParenBoth:
232 mnNumberingType <<= NumberingType::CHARS_THAI;
233 setSuffixParenBoth();
234 break;
235 case XML_thaiAlphaParenR:
236 case XML_thaiNumParenR:
237 mnNumberingType <<= NumberingType::CHARS_THAI;
238 setSuffixParenRight();
239 break;
240 case XML_thaiAlphaPeriod:
241 case XML_thaiNumPeriod:
242 mnNumberingType <<= NumberingType::CHARS_THAI;
243 setSuffixPeriod();
244 break;
248 void BulletList::setBulletSize(sal_Int16 nSize)
250 mnSize <<= nSize;
253 void BulletList::setFontSize(sal_Int16 nSize)
255 mnFontSize <<= nSize;
258 void BulletList::apply( const BulletList& rSource )
260 if ( rSource.maBulletColorPtr->isUsed() )
261 maBulletColorPtr = rSource.maBulletColorPtr;
262 if ( rSource.mbBulletColorFollowText.hasValue() )
263 mbBulletColorFollowText = rSource.mbBulletColorFollowText;
264 if ( rSource.mbBulletFontFollowText.hasValue() )
265 mbBulletFontFollowText = rSource.mbBulletFontFollowText;
266 maBulletFont.assignIfUsed( rSource.maBulletFont );
267 if ( rSource.msBulletChar.hasValue() )
268 msBulletChar = rSource.msBulletChar;
269 if ( rSource.mnStartAt.hasValue() )
270 mnStartAt = rSource.mnStartAt;
271 if ( rSource.mnNumberingType.hasValue() )
272 mnNumberingType = rSource.mnNumberingType;
273 if ( rSource.msNumberingPrefix.hasValue() )
274 msNumberingPrefix = rSource.msNumberingPrefix;
275 if ( rSource.msNumberingSuffix.hasValue() )
276 msNumberingSuffix = rSource.msNumberingSuffix;
277 if ( rSource.mnSize.hasValue() )
278 mnSize = rSource.mnSize;
279 if ( rSource.mnFontSize.hasValue() )
280 mnFontSize = rSource.mnFontSize;
281 if ( rSource.maStyleName.hasValue() )
282 maStyleName = rSource.maStyleName;
283 if ( rSource.maGraphic.hasValue() )
284 maGraphic = rSource.maGraphic;
287 void BulletList::pushToPropMap( const ::oox::core::XmlFilterBase* pFilterBase, PropertyMap& rPropMap ) const
289 if( msNumberingPrefix.hasValue() )
290 rPropMap.setAnyProperty( PROP_Prefix, msNumberingPrefix);
291 if( msNumberingSuffix.hasValue() )
292 rPropMap.setAnyProperty( PROP_Suffix, msNumberingSuffix);
293 if( mnStartAt.hasValue() )
294 rPropMap.setAnyProperty( PROP_StartWith, mnStartAt);
295 rPropMap.setProperty( PROP_Adjust, HoriOrientation::LEFT);
297 if( mnNumberingType.hasValue() )
298 rPropMap.setAnyProperty( PROP_NumberingType, mnNumberingType);
300 OUString aBulletFontName;
301 sal_Int16 nBulletFontPitch = 0;
302 sal_Int16 nBulletFontFamily = 0;
303 bool bSymbolFont = false;
304 if( pFilterBase) {
305 if (maBulletFont.getFontData( aBulletFontName, nBulletFontPitch, nBulletFontFamily, *pFilterBase ) )
307 FontDescriptor aFontDesc;
308 sal_Int16 nFontSize = 0;
309 if( mnFontSize >>= nFontSize )
310 aFontDesc.Height = nFontSize;
312 // TODO move the to the TextFont struct.
313 aFontDesc.Name = aBulletFontName;
314 aFontDesc.Pitch = nBulletFontPitch;
315 aFontDesc.Family = nBulletFontFamily;
316 if ( aBulletFontName.equalsIgnoreAsciiCase("Wingdings") ||
317 aBulletFontName.equalsIgnoreAsciiCase("Wingdings 2") ||
318 aBulletFontName.equalsIgnoreAsciiCase("Wingdings 3") ||
319 aBulletFontName.equalsIgnoreAsciiCase("Monotype Sorts") ||
320 aBulletFontName.equalsIgnoreAsciiCase("Monotype Sorts 2") ||
321 aBulletFontName.equalsIgnoreAsciiCase("Webdings") ||
322 aBulletFontName.equalsIgnoreAsciiCase("StarBats") ||
323 aBulletFontName.equalsIgnoreAsciiCase("StarMath") ||
324 aBulletFontName.equalsIgnoreAsciiCase("ZapfDingbats") ) {
325 aFontDesc.CharSet = RTL_TEXTENCODING_SYMBOL;
326 bSymbolFont = true;
328 rPropMap.setProperty( PROP_BulletFont, aFontDesc);
329 rPropMap.setProperty( PROP_BulletFontName, aBulletFontName);
332 if ( msBulletChar.hasValue() ) {
333 OUString sBuChar;
335 msBulletChar >>= sBuChar;
337 if( pFilterBase && sBuChar.getLength() == 1 && maBulletFont.getFontData( aBulletFontName, nBulletFontPitch, nBulletFontFamily, *pFilterBase ) && bSymbolFont )
339 sal_Unicode nBuChar = sBuChar.toChar();
340 nBuChar &= 0x00ff;
341 nBuChar |= 0xf000;
342 sBuChar = OUString( &nBuChar, 1 );
345 rPropMap.setProperty( PROP_BulletChar, sBuChar);
347 if ( maGraphic.hasValue() )
349 Reference< css::awt::XBitmap > xBitmap( maGraphic, UNO_QUERY );
350 if ( xBitmap.is() )
351 rPropMap.setProperty( PROP_Graphic, xBitmap);
353 if( mnSize.hasValue() )
354 rPropMap.setAnyProperty( PROP_BulletRelSize, mnSize);
355 if ( maStyleName.hasValue() )
356 rPropMap.setAnyProperty( PROP_CharStyleName, maStyleName);
357 if (pFilterBase ) {
358 bool bFollowTextColor = false;
359 mbBulletColorFollowText >>= bFollowTextColor;
360 if ( maBulletColorPtr->isUsed() && !bFollowTextColor )
361 rPropMap.setProperty( PROP_BulletColor, maBulletColorPtr->getColor( pFilterBase->getGraphicHelper() ));
365 TextParagraphProperties::TextParagraphProperties()
366 : mnLevel( 0 )
370 TextParagraphProperties::~TextParagraphProperties()
374 void TextParagraphProperties::apply( const TextParagraphProperties& rSourceProps )
376 maTextParagraphPropertyMap.assignAll( rSourceProps.maTextParagraphPropertyMap );
377 maBulletList.apply( rSourceProps.maBulletList );
378 maTextCharacterProperties.assignUsed( rSourceProps.maTextCharacterProperties );
379 if ( rSourceProps.maParaTopMargin.bHasValue )
380 maParaTopMargin = rSourceProps.maParaTopMargin;
381 if ( rSourceProps.maParaBottomMargin.bHasValue )
382 maParaBottomMargin = rSourceProps.maParaBottomMargin;
383 if ( rSourceProps.moParaLeftMargin )
384 moParaLeftMargin = rSourceProps.moParaLeftMargin;
385 if ( rSourceProps.moFirstLineIndentation )
386 moFirstLineIndentation = rSourceProps.moFirstLineIndentation;
387 if( rSourceProps.mnLevel )
388 mnLevel = rSourceProps.mnLevel;
389 if( rSourceProps.moParaAdjust )
390 moParaAdjust = rSourceProps.moParaAdjust;
393 void TextParagraphProperties::pushToPropSet( const ::oox::core::XmlFilterBase* pFilterBase,
394 const Reference < XPropertySet >& xPropSet, PropertyMap& rioBulletMap, const BulletList* pMasterBuList, bool bApplyBulletMap, float fCharacterSize,
395 bool bPushDefaultValues ) const
397 PropertySet aPropSet( xPropSet );
398 aPropSet.setProperties( maTextParagraphPropertyMap );
400 sal_Int32 nNumberingType = NumberingType::NUMBER_NONE;
401 if ( maBulletList.mnNumberingType.hasValue() )
402 maBulletList.mnNumberingType >>= nNumberingType;
403 else if ( pMasterBuList && pMasterBuList->mnNumberingType.hasValue() )
404 pMasterBuList->mnNumberingType >>= nNumberingType;
405 if ( nNumberingType == NumberingType::NUMBER_NONE )
406 aPropSet.setProperty< sal_Int16 >( PROP_NumberingLevel, -1 );
408 maBulletList.pushToPropMap( pFilterBase, rioBulletMap );
410 if ( maParaTopMargin.bHasValue || bPushDefaultValues )
411 aPropSet.setProperty( PROP_ParaTopMargin, maParaTopMargin.toMargin( fCharacterSize != 0.0 ? fCharacterSize : getCharHeightPoints ( 12.0 ) ) );
412 if ( maParaBottomMargin.bHasValue || bPushDefaultValues )
413 aPropSet.setProperty( PROP_ParaBottomMargin, maParaBottomMargin.toMargin( fCharacterSize != 0.0 ? fCharacterSize : getCharHeightPoints ( 12.0 ) ) );
414 if ( nNumberingType == NumberingType::BITMAP )
416 fCharacterSize = getCharHeightPoints( fCharacterSize );
418 css::awt::Size aBulletSize;
419 aBulletSize.Width = aBulletSize.Height = static_cast< sal_Int32 >( ( fCharacterSize * ( 2540.0 / 72.0 ) * 0.8 ) );
420 rioBulletMap.setProperty( PROP_GraphicSize, aBulletSize);
423 boost::optional< sal_Int32 > noParaLeftMargin( moParaLeftMargin );
424 boost::optional< sal_Int32 > noFirstLineIndentation( moFirstLineIndentation );
426 if ( nNumberingType != NumberingType::NUMBER_NONE )
428 if ( noParaLeftMargin )
430 aPropSet.setProperty<sal_Int32>( PROP_ParaLeftMargin, 0);
431 rioBulletMap.setProperty( PROP_LeftMargin, *noParaLeftMargin);
432 noParaLeftMargin = boost::none;
434 if ( noFirstLineIndentation )
436 // Force Paragraph property as zero - impress seems to use the value from previous
437 // (non) bullet line if not set to zero explicitly :(
438 aPropSet.setProperty<sal_Int32>( PROP_ParaFirstLineIndent, 0);
439 rioBulletMap.setProperty( PROP_FirstLineOffset, *noFirstLineIndentation);
440 noFirstLineIndentation = boost::none;
442 if ( nNumberingType != NumberingType::BITMAP && !rioBulletMap.hasProperty( PROP_BulletColor ) && pFilterBase )
443 rioBulletMap.setProperty( PROP_BulletColor, maTextCharacterProperties.maFillProperties.getBestSolidColor().getColor( pFilterBase->getGraphicHelper()));
446 if ( bApplyBulletMap )
448 Reference< XIndexReplace > xNumRule;
449 aPropSet.getProperty( xNumRule, PROP_NumberingRules );
450 OSL_ENSURE( xNumRule.is(), "can't get Numbering rules");
454 if( xNumRule.is() )
456 if( !rioBulletMap.empty() )
458 // fix default bullet size to be 100%
459 if( !rioBulletMap.hasProperty( PROP_BulletRelSize ) )
460 rioBulletMap.setProperty<sal_Int16>( PROP_BulletRelSize, 100);
461 Sequence< PropertyValue > aBulletPropSeq = rioBulletMap.makePropertyValueSequence();
462 xNumRule->replaceByIndex( getLevel(), makeAny( aBulletPropSeq ) );
465 aPropSet.setProperty( PROP_NumberingRules, xNumRule );
468 catch (const Exception &)
470 // Don't warn for now, expected to fail for Writer.
473 if ( noParaLeftMargin )
474 aPropSet.setProperty( PROP_ParaLeftMargin, *noParaLeftMargin);
475 if ( noFirstLineIndentation )
477 aPropSet.setProperty( PROP_ParaFirstLineIndent, *noFirstLineIndentation );
478 if( bPushDefaultValues )
480 // Reset TabStops - these would be auto calculated by Impress
481 TabStop aTabStop;
482 aTabStop.Position = 0;
483 Sequence< TabStop > aSeq(1);
484 aSeq[0] = aTabStop;
485 aPropSet.setProperty( PROP_ParaTabStops, aSeq );
489 if ( moParaAdjust )
491 aPropSet.setProperty( PROP_ParaAdjust, moParaAdjust.get());
493 else
495 aPropSet.setProperty( PROP_ParaAdjust, css::style::ParagraphAdjust_LEFT);
499 float TextParagraphProperties::getCharHeightPoints( float fDefault ) const
501 return maTextCharacterProperties.getCharHeightPoints( fDefault );
504 #ifdef DBG_UTIL
505 // Note: Please don't remove this function. This is required for
506 // debugging pptx import problems.
507 void TextParagraphProperties::dump() const
509 Reference< css::drawing::XShape > xShape( oox::ppt::PowerPointImport::mpDebugFilterBase->getModelFactory()->createInstance( "com.sun.star.presentation.TitleTextShape" ), UNO_QUERY );
510 Reference< css::text::XText > xText( xShape, UNO_QUERY );
512 Reference< css::drawing::XDrawPage > xDebugPage(ppt::SlidePersist::mxDebugPage.get(), UNO_QUERY);
513 if (xDebugPage.is())
514 xDebugPage->add( xShape );
516 PropertyMap emptyMap;
518 const OUString sText = "debug";
519 xText->setString( sText );
520 Reference< css::text::XTextCursor > xStart( xText->createTextCursor(), UNO_QUERY );
521 Reference< css::text::XTextRange > xRange( xStart, UNO_QUERY );
522 xStart->gotoEnd( true );
523 Reference< XPropertySet > xPropSet( xRange, UNO_QUERY );
524 pushToPropSet( nullptr, xPropSet, emptyMap, nullptr, false, 0 );
525 PropertySet aPropSet( xPropSet );
526 aPropSet.dump();
528 #endif
531 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */