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 
BulletList()50 BulletList::BulletList( )
51 : maBulletColorPtr( new Color() )
52 {
53 }
54 
is() const55 bool BulletList::is() const
56 {
57 	return mnNumberingType.hasValue();
58 }
59 
setBulletChar(const::rtl::OUString & sChar)60 void BulletList::setBulletChar( const ::rtl::OUString & sChar )
61 {
62 	mnNumberingType <<= NumberingType::CHAR_SPECIAL;
63 	msBulletChar <<= sChar;
64 }
65 
setGraphic(::com::sun::star::uno::Reference<::com::sun::star::graphic::XGraphic> & rXGraphic)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 
setNone()72 void BulletList::setNone( )
73 {
74 	mnNumberingType <<= NumberingType::NUMBER_NONE;
75 }
76 
setSuffixParenBoth()77 void BulletList::setSuffixParenBoth()
78 {
79 	msNumberingSuffix <<= CREATE_OUSTRING( ")" );
80 	msNumberingPrefix <<= CREATE_OUSTRING( "(" );
81 }
82 
setSuffixParenRight()83 void BulletList::setSuffixParenRight()
84 {
85 	msNumberingSuffix <<= CREATE_OUSTRING( ")" );
86 	msNumberingPrefix <<= OUString();
87 }
88 
setSuffixPeriod()89 void BulletList::setSuffixPeriod()
90 {
91 	msNumberingSuffix <<= CREATE_OUSTRING( "." );
92 	msNumberingPrefix <<= OUString();
93 }
94 
setSuffixNone()95 void BulletList::setSuffixNone()
96 {
97 	msNumberingSuffix <<= OUString();
98 	msNumberingPrefix <<= OUString();
99 }
100 
setSuffixMinusRight()101 void BulletList::setSuffixMinusRight()
102 {
103 	msNumberingSuffix <<= CREATE_OUSTRING( "-" );
104 	msNumberingPrefix <<= OUString();
105 }
106 
setType(sal_Int32 nType)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 
setBulletSize(sal_Int16 nSize)235 void BulletList::setBulletSize(sal_Int16 nSize)
236 {
237 	mnSize <<= nSize;
238 }
239 
240 
setFontSize(sal_Int16 nSize)241 void BulletList::setFontSize(sal_Int16 nSize)
242 {
243 	mnFontSize <<= nSize;
244 }
245 
apply(const BulletList & rSource)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 
pushToPropMap(const::oox::core::XmlFilterBase & rFilterBase,PropertyMap & rPropMap) const275 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 
TextParagraphProperties()321 TextParagraphProperties::TextParagraphProperties()
322 : mnLevel( 0 )
323 {
324 }
325 
~TextParagraphProperties()326 TextParagraphProperties::~TextParagraphProperties()
327 {
328 }
329 
apply(const TextParagraphProperties & rSourceProps)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 
pushToPropSet(const::oox::core::XmlFilterBase & rFilterBase,const Reference<XPropertySet> & xPropSet,PropertyMap & rioBulletMap,const BulletList * pMasterBuList,sal_Bool bApplyBulletMap,float fCharacterSize) const345 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 
getCharHeightPoints(float fDefault) const414 float TextParagraphProperties::getCharHeightPoints( float fDefault ) const
415 {
416     return maTextCharacterProperties.getCharHeightPoints( fDefault );
417 }
418 
419 } }
420