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