1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "oox/drawingml/textparagraphproperties.hxx" 29 30 #include <com/sun/star/text/XNumberingRulesSupplier.hpp> 31 #include <com/sun/star/container/XIndexReplace.hpp> 32 #include <com/sun/star/text/HoriOrientation.hpp> 33 #include <com/sun/star/awt/FontDescriptor.hpp> 34 #include <com/sun/star/awt/XBitmap.hpp> 35 #include <com/sun/star/graphic/XGraphic.hpp> 36 #include <com/sun/star/beans/PropertyValue.hpp> 37 38 #include "oox/helper/helper.hxx" 39 #include "oox/helper/propertyset.hxx" 40 #include "oox/core/xmlfilterbase.hxx" 41 #include "oox/drawingml/drawingmltypes.hxx" 42 43 using rtl::OUString; 44 using namespace ::oox::core; 45 using namespace ::com::sun::star::uno; 46 using namespace ::com::sun::star::beans; 47 using namespace ::com::sun::star::style; 48 using namespace ::com::sun::star::text; 49 using namespace ::com::sun::star::container; 50 using ::com::sun::star::awt::FontDescriptor; 51 52 namespace oox { namespace drawingml { 53 54 BulletList::BulletList( ) 55 : maBulletColorPtr( new Color() ) 56 { 57 } 58 59 bool BulletList::is() const 60 { 61 return mnNumberingType.hasValue(); 62 } 63 64 void BulletList::setBulletChar( const ::rtl::OUString & sChar ) 65 { 66 mnNumberingType <<= NumberingType::CHAR_SPECIAL; 67 msBulletChar <<= sChar; 68 } 69 70 void BulletList::setGraphic( ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic >& rXGraphic ) 71 { 72 mnNumberingType <<= NumberingType::BITMAP; 73 maGraphic <<= rXGraphic; 74 } 75 76 void BulletList::setNone( ) 77 { 78 mnNumberingType <<= NumberingType::NUMBER_NONE; 79 } 80 81 void BulletList::setSuffixParenBoth() 82 { 83 msNumberingSuffix <<= CREATE_OUSTRING( ")" ); 84 msNumberingPrefix <<= CREATE_OUSTRING( "(" ); 85 } 86 87 void BulletList::setSuffixParenRight() 88 { 89 msNumberingSuffix <<= CREATE_OUSTRING( ")" ); 90 msNumberingPrefix <<= OUString(); 91 } 92 93 void BulletList::setSuffixPeriod() 94 { 95 msNumberingSuffix <<= CREATE_OUSTRING( "." ); 96 msNumberingPrefix <<= OUString(); 97 } 98 99 void BulletList::setSuffixNone() 100 { 101 msNumberingSuffix <<= OUString(); 102 msNumberingPrefix <<= OUString(); 103 } 104 105 void BulletList::setSuffixMinusRight() 106 { 107 msNumberingSuffix <<= CREATE_OUSTRING( "-" ); 108 msNumberingPrefix <<= OUString(); 109 } 110 111 void BulletList::setType( sal_Int32 nType ) 112 { 113 // OSL_TRACE( "OOX: set list numbering type %d", nType); 114 switch( nType ) 115 { 116 case XML_alphaLcParenBoth: 117 mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER; 118 setSuffixParenBoth(); 119 break; 120 case XML_alphaLcParenR: 121 mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER; 122 setSuffixParenRight(); 123 break; 124 case XML_alphaLcPeriod: 125 mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER; 126 setSuffixPeriod(); 127 break; 128 case XML_alphaUcParenBoth: 129 mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER; 130 setSuffixParenBoth(); 131 break; 132 case XML_alphaUcParenR: 133 mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER; 134 setSuffixParenRight(); 135 break; 136 case XML_alphaUcPeriod: 137 mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER; 138 setSuffixPeriod(); 139 break; 140 case XML_arabic1Minus: 141 case XML_arabic2Minus: 142 case XML_arabicDbPeriod: 143 case XML_arabicDbPlain: 144 // TODO 145 break; 146 case XML_arabicParenBoth: 147 mnNumberingType <<= NumberingType::ARABIC; 148 setSuffixParenBoth(); 149 break; 150 case XML_arabicParenR: 151 mnNumberingType <<= NumberingType::ARABIC; 152 setSuffixParenRight(); 153 break; 154 case XML_arabicPeriod: 155 mnNumberingType <<= NumberingType::ARABIC; 156 setSuffixPeriod(); 157 break; 158 case XML_arabicPlain: 159 mnNumberingType <<= NumberingType::ARABIC; 160 setSuffixNone(); 161 break; 162 case XML_circleNumDbPlain: 163 case XML_circleNumWdBlackPlain: 164 case XML_circleNumWdWhitePlain: 165 mnNumberingType <<= NumberingType::CIRCLE_NUMBER; 166 break; 167 case XML_ea1ChsPeriod: 168 mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH; 169 setSuffixPeriod(); 170 break; 171 case XML_ea1ChsPlain: 172 mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH; 173 setSuffixNone(); 174 break; 175 case XML_ea1ChtPeriod: 176 mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH_TW; 177 setSuffixPeriod(); 178 break; 179 case XML_ea1ChtPlain: 180 mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH_TW; 181 setSuffixNone(); 182 break; 183 case XML_ea1JpnChsDbPeriod: 184 case XML_ea1JpnKorPeriod: 185 case XML_ea1JpnKorPlain: 186 break; 187 case XML_hebrew2Minus: 188 mnNumberingType <<= NumberingType::CHARS_HEBREW; 189 setSuffixMinusRight(); 190 break; 191 case XML_hindiAlpha1Period: 192 case XML_hindiAlphaPeriod: 193 case XML_hindiNumParenR: 194 case XML_hindiNumPeriod: 195 // TODO 196 break; 197 case XML_romanLcParenBoth: 198 mnNumberingType <<= NumberingType::ROMAN_LOWER; 199 setSuffixParenBoth(); 200 break; 201 case XML_romanLcParenR: 202 mnNumberingType <<= NumberingType::ROMAN_LOWER; 203 setSuffixParenRight(); 204 break; 205 case XML_romanLcPeriod: 206 mnNumberingType <<= NumberingType::ROMAN_LOWER; 207 setSuffixPeriod(); 208 break; 209 case XML_romanUcParenBoth: 210 mnNumberingType <<= NumberingType::ROMAN_UPPER; 211 setSuffixParenBoth(); 212 break; 213 case XML_romanUcParenR: 214 mnNumberingType <<= NumberingType::ROMAN_UPPER; 215 setSuffixParenRight(); 216 break; 217 case XML_romanUcPeriod: 218 mnNumberingType <<= NumberingType::ROMAN_UPPER; 219 setSuffixPeriod(); 220 break; 221 case XML_thaiAlphaParenBoth: 222 case XML_thaiNumParenBoth: 223 mnNumberingType <<= NumberingType::CHARS_THAI; 224 setSuffixParenBoth(); 225 break; 226 case XML_thaiAlphaParenR: 227 case XML_thaiNumParenR: 228 mnNumberingType <<= NumberingType::CHARS_THAI; 229 setSuffixParenRight(); 230 break; 231 case XML_thaiAlphaPeriod: 232 case XML_thaiNumPeriod: 233 mnNumberingType <<= NumberingType::CHARS_THAI; 234 setSuffixPeriod(); 235 break; 236 } 237 } 238 239 void BulletList::setBulletSize(sal_Int16 nSize) 240 { 241 mnSize <<= nSize; 242 } 243 244 245 void BulletList::setFontSize(sal_Int16 nSize) 246 { 247 mnFontSize <<= nSize; 248 } 249 250 void BulletList::apply( const BulletList& rSource ) 251 { 252 if ( rSource.maBulletColorPtr->isUsed() ) 253 maBulletColorPtr = rSource.maBulletColorPtr; 254 if ( rSource.mbBulletColorFollowText.hasValue() ) 255 mbBulletColorFollowText = rSource.mbBulletColorFollowText; 256 if ( rSource.mbBulletFontFollowText.hasValue() ) 257 mbBulletFontFollowText = rSource.mbBulletFontFollowText; 258 maBulletFont.assignIfUsed( rSource.maBulletFont ); 259 if ( rSource.msBulletChar.hasValue() ) 260 msBulletChar = rSource.msBulletChar; 261 if ( rSource.mnStartAt.hasValue() ) 262 mnStartAt = rSource.mnStartAt; 263 if ( rSource.mnNumberingType.hasValue() ) 264 mnNumberingType = rSource.mnNumberingType; 265 if ( rSource.msNumberingPrefix.hasValue() ) 266 msNumberingPrefix = rSource.msNumberingPrefix; 267 if ( rSource.msNumberingSuffix.hasValue() ) 268 msNumberingSuffix = rSource.msNumberingSuffix; 269 if ( rSource.mnSize.hasValue() ) 270 mnSize = rSource.mnSize; 271 if ( rSource.mnFontSize.hasValue() ) 272 mnFontSize = rSource.mnFontSize; 273 if ( rSource.maStyleName.hasValue() ) 274 maStyleName = rSource.maStyleName; 275 if ( rSource.maGraphic.hasValue() ) 276 maGraphic = rSource.maGraphic; 277 } 278 279 void BulletList::pushToPropMap( const ::oox::core::XmlFilterBase& rFilterBase, PropertyMap& rPropMap ) const 280 { 281 if( msNumberingPrefix.hasValue() ) 282 rPropMap[ PROP_Prefix ] = msNumberingPrefix; 283 if( msNumberingSuffix.hasValue() ) 284 rPropMap[ PROP_Suffix ] = msNumberingSuffix; 285 if( mnStartAt.hasValue() ) 286 rPropMap[ PROP_StartWith ] = mnStartAt; 287 rPropMap[ PROP_Adjust ] <<= HoriOrientation::LEFT; 288 289 if( mnNumberingType.hasValue() ) 290 rPropMap[ PROP_NumberingType ] = mnNumberingType; 291 292 OUString aBulletFontName; 293 sal_Int16 nBulletFontPitch = 0; 294 sal_Int16 nBulletFontFamily = 0; 295 if( maBulletFont.getFontData( aBulletFontName, nBulletFontPitch, nBulletFontFamily, rFilterBase ) ) 296 { 297 FontDescriptor aFontDesc; 298 sal_Int16 nFontSize = 0; 299 if( mnFontSize >>= nFontSize ) 300 aFontDesc.Height = nFontSize; 301 302 // TODO move the to the TextFont struct. 303 aFontDesc.Name = aBulletFontName; 304 aFontDesc.Pitch = nBulletFontPitch; 305 aFontDesc.Family = nBulletFontFamily; 306 rPropMap[ PROP_BulletFont ] <<= aFontDesc; 307 rPropMap[ PROP_BulletFontName ] <<= aBulletFontName; 308 } 309 if ( msBulletChar.hasValue() ) 310 rPropMap[ PROP_BulletChar ] = msBulletChar; 311 if ( maGraphic.hasValue() ) 312 { 313 Reference< com::sun::star::awt::XBitmap > xBitmap( maGraphic, UNO_QUERY ); 314 if ( xBitmap.is() ) 315 rPropMap[ PROP_Graphic ] <<= xBitmap; 316 } 317 if( mnSize.hasValue() ) 318 rPropMap[ PROP_BulletRelSize ] = mnSize; 319 if ( maStyleName.hasValue() ) 320 rPropMap[ PROP_CharStyleName ] <<= maStyleName; 321 if ( maBulletColorPtr->isUsed() ) 322 rPropMap[ PROP_BulletColor ] <<= maBulletColorPtr->getColor( rFilterBase.getGraphicHelper() ); 323 } 324 325 TextParagraphProperties::TextParagraphProperties() 326 : mnLevel( 0 ) 327 { 328 } 329 330 TextParagraphProperties::~TextParagraphProperties() 331 { 332 } 333 334 void TextParagraphProperties::apply( const TextParagraphProperties& rSourceProps ) 335 { 336 maTextParagraphPropertyMap.insert( rSourceProps.maTextParagraphPropertyMap.begin(), rSourceProps.maTextParagraphPropertyMap.end() ); 337 maBulletList.apply( rSourceProps.maBulletList ); 338 maTextCharacterProperties.assignUsed( rSourceProps.maTextCharacterProperties ); 339 if ( rSourceProps.maParaTopMargin.bHasValue ) 340 maParaTopMargin = rSourceProps.maParaTopMargin; 341 if ( rSourceProps.maParaBottomMargin.bHasValue ) 342 maParaBottomMargin = rSourceProps.maParaBottomMargin; 343 if ( rSourceProps.moParaLeftMargin ) 344 moParaLeftMargin = rSourceProps.moParaLeftMargin; 345 if ( rSourceProps.moFirstLineIndentation ) 346 moFirstLineIndentation = rSourceProps.moFirstLineIndentation; 347 } 348 349 void TextParagraphProperties::pushToPropSet( const ::oox::core::XmlFilterBase& rFilterBase, 350 const Reference < XPropertySet >& xPropSet, PropertyMap& rioBulletMap, const BulletList* pMasterBuList, sal_Bool bApplyBulletMap, float fCharacterSize ) const 351 { 352 PropertySet aPropSet( xPropSet ); 353 aPropSet.setProperties( maTextParagraphPropertyMap ); 354 355 sal_Int32 nNumberingType = NumberingType::NUMBER_NONE; 356 if ( maBulletList.mnNumberingType.hasValue() ) 357 maBulletList.mnNumberingType >>= nNumberingType; 358 else if ( pMasterBuList && pMasterBuList->mnNumberingType.hasValue() ) 359 pMasterBuList->mnNumberingType >>= nNumberingType; 360 if ( nNumberingType == NumberingType::NUMBER_NONE ) 361 aPropSet.setProperty< sal_Int16 >( PROP_NumberingLevel, -1 ); 362 363 maBulletList.pushToPropMap( rFilterBase, rioBulletMap ); 364 365 if ( maParaTopMargin.bHasValue ) 366 aPropSet.setProperty( PROP_ParaTopMargin, maParaTopMargin.toMargin( getCharHeightPoints( 18.0 ) ) ); 367 if ( maParaBottomMargin.bHasValue ) 368 aPropSet.setProperty( PROP_ParaBottomMargin, maParaBottomMargin.toMargin( getCharHeightPoints( 18.0 ) ) ); 369 if ( nNumberingType == NumberingType::BITMAP ) 370 { 371 fCharacterSize = getCharHeightPoints( fCharacterSize ); 372 373 com::sun::star::awt::Size aBulletSize; 374 aBulletSize.Width = aBulletSize.Height = static_cast< sal_Int32 >( ( fCharacterSize * ( 2540.0 / 72.0 ) * 0.8 ) ); 375 rioBulletMap[ PROP_GraphicSize ] <<= aBulletSize; 376 } 377 378 boost::optional< sal_Int32 > noParaLeftMargin( moParaLeftMargin ); 379 boost::optional< sal_Int32 > noFirstLineIndentation( moFirstLineIndentation ); 380 381 if ( nNumberingType != NumberingType::NUMBER_NONE ) 382 { 383 if ( noParaLeftMargin ) 384 { 385 rioBulletMap[ PROP_LeftMargin ] <<= static_cast< sal_Int32 >( *noParaLeftMargin ); 386 noParaLeftMargin = boost::optional< sal_Int32 >( 0 ); 387 } 388 if ( noFirstLineIndentation ) 389 { 390 rioBulletMap[ PROP_FirstLineOffset ] <<= static_cast< sal_Int32 >( *noFirstLineIndentation ); 391 noFirstLineIndentation = boost::optional< sal_Int32 >( 0 ); 392 } 393 } 394 395 if ( bApplyBulletMap ) 396 { 397 Reference< XIndexReplace > xNumRule; 398 aPropSet.getProperty( xNumRule, PROP_NumberingRules ); 399 OSL_ENSURE( xNumRule.is(), "can't get Numbering rules"); 400 401 if( xNumRule.is() ) 402 { 403 if( !rioBulletMap.empty() ) 404 { 405 Sequence< PropertyValue > aBulletPropSeq = rioBulletMap.makePropertyValueSequence(); 406 xNumRule->replaceByIndex( getLevel(), makeAny( aBulletPropSeq ) ); 407 } 408 409 aPropSet.setProperty( PROP_NumberingRules, xNumRule ); 410 } 411 } 412 if ( noParaLeftMargin ) 413 aPropSet.setProperty( PROP_ParaLeftMargin, *noParaLeftMargin ); 414 if ( noFirstLineIndentation ) 415 aPropSet.setProperty( PROP_ParaFirstLineIndent, *noFirstLineIndentation ); 416 } 417 418 float TextParagraphProperties::getCharHeightPoints( float fDefault ) const 419 { 420 return maTextCharacterProperties.getCharHeightPoints( fDefault ); 421 } 422 423 } } 424