Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / oox / source / drawingml / textparagraphproperties.cxx
blobf1c966deeaa41e911e1e2410fc4f4da49bd31410
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 <oox/ppt/pptimport.hxx>
49 #include <oox/ppt/slidepersist.hxx>
50 #endif
52 using namespace ::oox::core;
53 using namespace ::com::sun::star::uno;
54 using namespace ::com::sun::star::beans;
55 using namespace ::com::sun::star::style;
56 using namespace ::com::sun::star::text;
57 using namespace ::com::sun::star::container;
58 using ::com::sun::star::awt::FontDescriptor;
60 namespace oox { namespace drawingml {
62 BulletList::BulletList( )
63 : maBulletColorPtr( new Color() )
67 bool BulletList::is() const
69 return mnNumberingType.hasValue();
72 void BulletList::setBulletChar( const OUString & sChar )
74 mnNumberingType <<= NumberingType::CHAR_SPECIAL;
75 msBulletChar <<= sChar;
78 void BulletList::setGraphic( css::uno::Reference< css::graphic::XGraphic > const & rXGraphic )
80 mnNumberingType <<= NumberingType::BITMAP;
81 maGraphic <<= rXGraphic;
84 void BulletList::setNone( )
86 mnNumberingType <<= NumberingType::NUMBER_NONE;
89 void BulletList::setSuffixParenBoth()
91 msNumberingSuffix <<= OUString( ")" );
92 msNumberingPrefix <<= OUString( "(" );
95 void BulletList::setSuffixParenRight()
97 msNumberingSuffix <<= OUString( ")" );
98 msNumberingPrefix <<= OUString();
101 void BulletList::setSuffixPeriod()
103 msNumberingSuffix <<= OUString( "." );
104 msNumberingPrefix <<= OUString();
107 void BulletList::setSuffixNone()
109 msNumberingSuffix <<= OUString();
110 msNumberingPrefix <<= OUString();
113 void BulletList::setSuffixMinusRight()
115 msNumberingSuffix <<= OUString( "-" );
116 msNumberingPrefix <<= OUString();
119 void BulletList::setType( sal_Int32 nType )
121 OSL_ASSERT((nType & sal_Int32(0xFFFF0000))==0);
122 switch( nType )
124 case XML_alphaLcParenBoth:
125 mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER;
126 setSuffixParenBoth();
127 break;
128 case XML_alphaLcParenR:
129 mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER;
130 setSuffixParenRight();
131 break;
132 case XML_alphaLcPeriod:
133 mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER;
134 setSuffixPeriod();
135 break;
136 case XML_alphaUcParenBoth:
137 mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER;
138 setSuffixParenBoth();
139 break;
140 case XML_alphaUcParenR:
141 mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER;
142 setSuffixParenRight();
143 break;
144 case XML_alphaUcPeriod:
145 mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER;
146 setSuffixPeriod();
147 break;
148 case XML_arabic1Minus:
149 case XML_arabic2Minus:
150 case XML_arabicDbPeriod:
151 case XML_arabicDbPlain:
152 // TODO
153 break;
154 case XML_arabicParenBoth:
155 mnNumberingType <<= NumberingType::ARABIC;
156 setSuffixParenBoth();
157 break;
158 case XML_arabicParenR:
159 mnNumberingType <<= NumberingType::ARABIC;
160 setSuffixParenRight();
161 break;
162 case XML_arabicPeriod:
163 mnNumberingType <<= NumberingType::ARABIC;
164 setSuffixPeriod();
165 break;
166 case XML_arabicPlain:
167 mnNumberingType <<= NumberingType::ARABIC;
168 setSuffixNone();
169 break;
170 case XML_circleNumDbPlain:
171 case XML_circleNumWdBlackPlain:
172 case XML_circleNumWdWhitePlain:
173 mnNumberingType <<= NumberingType::CIRCLE_NUMBER;
174 break;
175 case XML_ea1ChsPeriod:
176 mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH;
177 setSuffixPeriod();
178 break;
179 case XML_ea1ChsPlain:
180 mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH;
181 setSuffixNone();
182 break;
183 case XML_ea1ChtPeriod:
184 mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH_TW;
185 setSuffixPeriod();
186 break;
187 case XML_ea1ChtPlain:
188 mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH_TW;
189 setSuffixNone();
190 break;
191 case XML_ea1JpnChsDbPeriod:
192 case XML_ea1JpnKorPeriod:
193 case XML_ea1JpnKorPlain:
194 break;
195 case XML_hebrew2Minus:
196 mnNumberingType <<= NumberingType::CHARS_HEBREW;
197 setSuffixMinusRight();
198 break;
199 case XML_hindiAlpha1Period:
200 case XML_hindiAlphaPeriod:
201 case XML_hindiNumParenR:
202 case XML_hindiNumPeriod:
203 // TODO
204 break;
205 case XML_romanLcParenBoth:
206 mnNumberingType <<= NumberingType::ROMAN_LOWER;
207 setSuffixParenBoth();
208 break;
209 case XML_romanLcParenR:
210 mnNumberingType <<= NumberingType::ROMAN_LOWER;
211 setSuffixParenRight();
212 break;
213 case XML_romanLcPeriod:
214 mnNumberingType <<= NumberingType::ROMAN_LOWER;
215 setSuffixPeriod();
216 break;
217 case XML_romanUcParenBoth:
218 mnNumberingType <<= NumberingType::ROMAN_UPPER;
219 setSuffixParenBoth();
220 break;
221 case XML_romanUcParenR:
222 mnNumberingType <<= NumberingType::ROMAN_UPPER;
223 setSuffixParenRight();
224 break;
225 case XML_romanUcPeriod:
226 mnNumberingType <<= NumberingType::ROMAN_UPPER;
227 setSuffixPeriod();
228 break;
229 case XML_thaiAlphaParenBoth:
230 case XML_thaiNumParenBoth:
231 mnNumberingType <<= NumberingType::CHARS_THAI;
232 setSuffixParenBoth();
233 break;
234 case XML_thaiAlphaParenR:
235 case XML_thaiNumParenR:
236 mnNumberingType <<= NumberingType::CHARS_THAI;
237 setSuffixParenRight();
238 break;
239 case XML_thaiAlphaPeriod:
240 case XML_thaiNumPeriod:
241 mnNumberingType <<= NumberingType::CHARS_THAI;
242 setSuffixPeriod();
243 break;
247 void BulletList::setBulletSize(sal_Int16 nSize)
249 mnSize <<= nSize;
252 void BulletList::setFontSize(sal_Int16 nSize)
254 mnFontSize <<= nSize;
257 void BulletList::apply( const BulletList& rSource )
259 if ( rSource.maBulletColorPtr->isUsed() )
260 maBulletColorPtr = rSource.maBulletColorPtr;
261 if ( rSource.mbBulletColorFollowText.hasValue() )
262 mbBulletColorFollowText = rSource.mbBulletColorFollowText;
263 if ( rSource.mbBulletFontFollowText.hasValue() )
264 mbBulletFontFollowText = rSource.mbBulletFontFollowText;
265 maBulletFont.assignIfUsed( rSource.maBulletFont );
266 if ( rSource.msBulletChar.hasValue() )
267 msBulletChar = rSource.msBulletChar;
268 if ( rSource.mnStartAt.hasValue() )
269 mnStartAt = rSource.mnStartAt;
270 if ( rSource.mnNumberingType.hasValue() )
271 mnNumberingType = rSource.mnNumberingType;
272 if ( rSource.msNumberingPrefix.hasValue() )
273 msNumberingPrefix = rSource.msNumberingPrefix;
274 if ( rSource.msNumberingSuffix.hasValue() )
275 msNumberingSuffix = rSource.msNumberingSuffix;
276 if ( rSource.mnSize.hasValue() )
277 mnSize = rSource.mnSize;
278 if ( rSource.mnFontSize.hasValue() )
279 mnFontSize = rSource.mnFontSize;
280 if ( rSource.maStyleName.hasValue() )
281 maStyleName = rSource.maStyleName;
282 if ( rSource.maGraphic.hasValue() )
283 maGraphic = rSource.maGraphic;
286 void BulletList::pushToPropMap( const ::oox::core::XmlFilterBase* pFilterBase, PropertyMap& rPropMap ) const
288 if( msNumberingPrefix.hasValue() )
289 rPropMap.setAnyProperty( PROP_Prefix, msNumberingPrefix);
290 if( msNumberingSuffix.hasValue() )
291 rPropMap.setAnyProperty( PROP_Suffix, msNumberingSuffix);
292 if( mnStartAt.hasValue() )
293 rPropMap.setAnyProperty( PROP_StartWith, mnStartAt);
294 rPropMap.setProperty( PROP_Adjust, HoriOrientation::LEFT);
296 if( mnNumberingType.hasValue() )
297 rPropMap.setAnyProperty( PROP_NumberingType, mnNumberingType);
299 OUString aBulletFontName;
300 sal_Int16 nBulletFontPitch = 0;
301 sal_Int16 nBulletFontFamily = 0;
302 bool bSymbolFont = false;
303 if( pFilterBase) {
304 if (maBulletFont.getFontData( aBulletFontName, nBulletFontPitch, nBulletFontFamily, *pFilterBase ) )
306 FontDescriptor aFontDesc;
307 sal_Int16 nFontSize = 0;
308 if( mnFontSize >>= nFontSize )
309 aFontDesc.Height = nFontSize;
311 // TODO move the to the TextFont struct.
312 aFontDesc.Name = aBulletFontName;
313 aFontDesc.Pitch = nBulletFontPitch;
314 aFontDesc.Family = nBulletFontFamily;
315 if ( aBulletFontName.equalsIgnoreAsciiCase("Wingdings") ||
316 aBulletFontName.equalsIgnoreAsciiCase("Wingdings 2") ||
317 aBulletFontName.equalsIgnoreAsciiCase("Wingdings 3") ||
318 aBulletFontName.equalsIgnoreAsciiCase("Monotype Sorts") ||
319 aBulletFontName.equalsIgnoreAsciiCase("Monotype Sorts 2") ||
320 aBulletFontName.equalsIgnoreAsciiCase("Webdings") ||
321 aBulletFontName.equalsIgnoreAsciiCase("StarBats") ||
322 aBulletFontName.equalsIgnoreAsciiCase("StarMath") ||
323 aBulletFontName.equalsIgnoreAsciiCase("ZapfDingbats") ) {
324 aFontDesc.CharSet = RTL_TEXTENCODING_SYMBOL;
325 bSymbolFont = true;
327 rPropMap.setProperty( PROP_BulletFont, aFontDesc);
328 rPropMap.setProperty( PROP_BulletFontName, aBulletFontName);
331 if ( msBulletChar.hasValue() ) {
332 OUString sBuChar;
334 msBulletChar >>= sBuChar;
336 if( pFilterBase && sBuChar.getLength() == 1 && maBulletFont.getFontData( aBulletFontName, nBulletFontPitch, nBulletFontFamily, *pFilterBase ) && bSymbolFont )
338 sal_Unicode nBuChar = sBuChar.toChar();
339 nBuChar &= 0x00ff;
340 nBuChar |= 0xf000;
341 sBuChar = OUString( &nBuChar, 1 );
344 rPropMap.setProperty( PROP_BulletChar, sBuChar);
346 if ( maGraphic.hasValue() )
348 Reference<css::awt::XBitmap> xBitmap(maGraphic, UNO_QUERY);
349 if (xBitmap.is())
350 rPropMap.setProperty(PROP_GraphicBitmap, xBitmap);
352 if( mnSize.hasValue() )
353 rPropMap.setAnyProperty( PROP_BulletRelSize, mnSize);
354 if ( maStyleName.hasValue() )
355 rPropMap.setAnyProperty( PROP_CharStyleName, maStyleName);
356 if (pFilterBase ) {
357 bool bFollowTextColor = false;
358 mbBulletColorFollowText >>= bFollowTextColor;
359 if ( maBulletColorPtr->isUsed() && !bFollowTextColor )
360 rPropMap.setProperty( PROP_BulletColor, maBulletColorPtr->getColor( pFilterBase->getGraphicHelper() ));
364 TextParagraphProperties::TextParagraphProperties()
365 : mnLevel( 0 )
369 void TextParagraphProperties::apply( const TextParagraphProperties& rSourceProps )
371 maTextParagraphPropertyMap.assignAll( rSourceProps.maTextParagraphPropertyMap );
372 maBulletList.apply( rSourceProps.maBulletList );
373 maTextCharacterProperties.assignUsed( rSourceProps.maTextCharacterProperties );
374 if ( rSourceProps.maParaTopMargin.bHasValue )
375 maParaTopMargin = rSourceProps.maParaTopMargin;
376 if ( rSourceProps.maParaBottomMargin.bHasValue )
377 maParaBottomMargin = rSourceProps.maParaBottomMargin;
378 if ( rSourceProps.moParaLeftMargin )
379 moParaLeftMargin = rSourceProps.moParaLeftMargin;
380 if ( rSourceProps.moFirstLineIndentation )
381 moFirstLineIndentation = rSourceProps.moFirstLineIndentation;
382 if( rSourceProps.mnLevel )
383 mnLevel = rSourceProps.mnLevel;
384 if( rSourceProps.moParaAdjust )
385 moParaAdjust = rSourceProps.moParaAdjust;
386 if( rSourceProps.maLineSpacing.bHasValue )
387 maLineSpacing = rSourceProps.maLineSpacing;
390 void TextParagraphProperties::pushToPropSet( const ::oox::core::XmlFilterBase* pFilterBase,
391 const Reference < XPropertySet >& xPropSet, PropertyMap& rioBulletMap, const BulletList* pMasterBuList, bool bApplyBulletMap, float fCharacterSize,
392 bool bPushDefaultValues ) const
394 PropertySet aPropSet( xPropSet );
395 aPropSet.setProperties( maTextParagraphPropertyMap );
397 sal_Int32 nNumberingType = NumberingType::NUMBER_NONE;
398 if ( maBulletList.mnNumberingType.hasValue() )
399 maBulletList.mnNumberingType >>= nNumberingType;
400 else if ( pMasterBuList && pMasterBuList->mnNumberingType.hasValue() )
401 pMasterBuList->mnNumberingType >>= nNumberingType;
402 if ( nNumberingType == NumberingType::NUMBER_NONE )
403 aPropSet.setProperty< sal_Int16 >( PROP_NumberingLevel, -1 );
405 maBulletList.pushToPropMap( pFilterBase, rioBulletMap );
407 if ( maParaTopMargin.bHasValue || bPushDefaultValues )
408 aPropSet.setProperty( PROP_ParaTopMargin, maParaTopMargin.toMargin( fCharacterSize != 0.0 ? fCharacterSize : getCharHeightPoints ( 12.0 ) ) );
409 if ( maParaBottomMargin.bHasValue || bPushDefaultValues )
410 aPropSet.setProperty( PROP_ParaBottomMargin, maParaBottomMargin.toMargin( fCharacterSize != 0.0 ? fCharacterSize : getCharHeightPoints ( 12.0 ) ) );
412 boost::optional< sal_Int32 > noParaLeftMargin( moParaLeftMargin );
413 boost::optional< sal_Int32 > noFirstLineIndentation( moFirstLineIndentation );
415 if ( nNumberingType != NumberingType::NUMBER_NONE )
417 if ( noParaLeftMargin )
419 aPropSet.setProperty<sal_Int32>( PROP_ParaLeftMargin, 0);
420 rioBulletMap.setProperty( PROP_LeftMargin, *noParaLeftMargin);
421 noParaLeftMargin.reset();
423 if ( noFirstLineIndentation )
425 // Force Paragraph property as zero - impress seems to use the value from previous
426 // (non) bullet line if not set to zero explicitly :(
427 aPropSet.setProperty<sal_Int32>( PROP_ParaFirstLineIndent, 0);
428 rioBulletMap.setProperty( PROP_FirstLineOffset, *noFirstLineIndentation);
429 noFirstLineIndentation.reset();
431 if ( nNumberingType != NumberingType::BITMAP && !rioBulletMap.hasProperty( PROP_BulletColor ) && pFilterBase )
432 rioBulletMap.setProperty( PROP_BulletColor, maTextCharacterProperties.maFillProperties.getBestSolidColor().getColor( pFilterBase->getGraphicHelper()));
435 if ( bApplyBulletMap )
437 Reference< XIndexReplace > xNumRule;
438 aPropSet.getProperty( xNumRule, PROP_NumberingRules );
439 OSL_ENSURE( xNumRule.is(), "can't get Numbering rules");
443 if( xNumRule.is() )
445 if( !rioBulletMap.empty() )
447 // fix default bullet size to be 100%
448 if( !rioBulletMap.hasProperty( PROP_BulletRelSize ) )
449 rioBulletMap.setProperty<sal_Int16>( PROP_BulletRelSize, 100);
450 Sequence< PropertyValue > aBulletPropSeq = rioBulletMap.makePropertyValueSequence();
451 xNumRule->replaceByIndex( getLevel(), makeAny( aBulletPropSeq ) );
454 aPropSet.setProperty( PROP_NumberingRules, xNumRule );
457 catch (const Exception &)
459 // Don't warn for now, expected to fail for Writer.
462 if ( noParaLeftMargin )
463 aPropSet.setProperty( PROP_ParaLeftMargin, *noParaLeftMargin);
464 if ( noFirstLineIndentation )
466 aPropSet.setProperty( PROP_ParaFirstLineIndent, *noFirstLineIndentation );
467 if( bPushDefaultValues )
469 // Reset TabStops - these would be auto calculated by Impress
470 TabStop aTabStop;
471 aTabStop.Position = 0;
472 Sequence< TabStop > aSeq(1);
473 aSeq[0] = aTabStop;
474 aPropSet.setProperty( PROP_ParaTabStops, aSeq );
478 if ( moParaAdjust )
480 aPropSet.setProperty( PROP_ParaAdjust, moParaAdjust.get());
482 else
484 aPropSet.setProperty( PROP_ParaAdjust, css::style::ParagraphAdjust_LEFT);
487 if ( maLineSpacing.bHasValue )
489 aPropSet.setProperty( PROP_ParaLineSpacing, maLineSpacing.toLineSpacing());
491 else
493 aPropSet.setProperty( PROP_ParaLineSpacing, css::style::LineSpacing( css::style::LineSpacingMode::PROP, 100 ));
497 float TextParagraphProperties::getCharHeightPoints( float fDefault ) const
499 return maTextCharacterProperties.getCharHeightPoints( fDefault );
502 #ifdef DBG_UTIL
503 // Note: Please don't remove this function. This is required for
504 // debugging pptx import problems.
505 void TextParagraphProperties::dump() const
507 Reference< css::drawing::XShape > xShape( oox::ppt::PowerPointImport::mpDebugFilterBase->getModelFactory()->createInstance( "com.sun.star.presentation.TitleTextShape" ), UNO_QUERY );
508 Reference< css::text::XText > xText( xShape, UNO_QUERY );
510 Reference< css::drawing::XDrawPage > xDebugPage(ppt::SlidePersist::mxDebugPage.get(), UNO_QUERY);
511 if (xDebugPage.is())
512 xDebugPage->add( xShape );
514 PropertyMap emptyMap;
516 const OUString sText = "debug";
517 xText->setString( sText );
518 Reference< css::text::XTextCursor > xStart = xText->createTextCursor();
519 xStart->gotoEnd( true );
520 Reference< XPropertySet > xPropSet( xStart, UNO_QUERY );
521 pushToPropSet( nullptr, xPropSet, emptyMap, nullptr, false, 0 );
522 PropertySet aPropSet( xPropSet );
523 aPropSet.dump();
525 #endif
528 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */