Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "drawingml/textparagraphpropertiescontext.hxx"
21 :
22 : #include <com/sun/star/text/WritingMode2.hpp>
23 : #include <com/sun/star/awt/FontDescriptor.hpp>
24 : #include <com/sun/star/style/ParagraphAdjust.hpp>
25 :
26 : #include <svx/unopage.hxx>
27 :
28 : #include "drawingml/colorchoicecontext.hxx"
29 : #include "drawingml/textcharacterpropertiescontext.hxx"
30 : #include "oox/drawingml/fillproperties.hxx"
31 : #include "oox/helper/attributelist.hxx"
32 : #include "textspacingcontext.hxx"
33 : #include "texttabstoplistcontext.hxx"
34 :
35 : using namespace ::oox::core;
36 : using ::com::sun::star::awt::FontDescriptor;
37 : using namespace ::com::sun::star::uno;
38 : using namespace ::com::sun::star::xml::sax;
39 : using namespace ::com::sun::star::style;
40 : using namespace ::com::sun::star::text;
41 :
42 : namespace oox { namespace drawingml {
43 :
44 : // CT_TextParagraphProperties
45 4838 : TextParagraphPropertiesContext::TextParagraphPropertiesContext( ContextHandler2Helper& rParent,
46 : const AttributeList& rAttribs,
47 : TextParagraphProperties& rTextParagraphProperties )
48 : : ContextHandler2( rParent )
49 : , mrTextParagraphProperties( rTextParagraphProperties )
50 4838 : , mrBulletList( rTextParagraphProperties.getBulletList() )
51 : {
52 4838 : OUString sValue;
53 :
54 4838 : PropertyMap& rPropertyMap( mrTextParagraphProperties.getTextParagraphPropertyMap() );
55 :
56 : // ST_TextAlignType
57 4838 : if ( rAttribs.hasAttribute( XML_algn ) )
58 : {
59 3301 : mrTextParagraphProperties.getParaAdjust() = GetParaAdjust( rAttribs.getToken( XML_algn, XML_l ) );
60 : }
61 : // TODO see to do the same with RubyAdjust
62 :
63 : // ST_Coordinate32
64 : // sValue = rAttribs.getString( XML_defTabSz ).get(); SJ: we need to be able to set the default tab size for each text object,
65 : // this is possible at the moment only for the whole document.
66 : // sal_Int32 nDefTabSize = ( sValue.getLength() == 0 ? 0 : GetCoordinate( sValue ) );
67 : // TODO
68 :
69 : // bool bEaLineBrk = rAttribs.getBool( XML_eaLnBrk, true );
70 4838 : if ( rAttribs.hasAttribute( XML_latinLnBrk ) )
71 : {
72 1686 : bool bLatinLineBrk = rAttribs.getBool( XML_latinLnBrk, true );
73 1686 : rPropertyMap.setProperty( PROP_ParaIsHyphenation, bLatinLineBrk);
74 : }
75 : // TODO see what to do with Asian hyphenation
76 :
77 : // ST_TextFontAlignType
78 : // TODO
79 : // sal_Int32 nFontAlign = rAttribs.getToken( XML_fontAlgn, XML_base );
80 :
81 4838 : if ( rAttribs.hasAttribute( XML_hangingPunct ) )
82 : {
83 2024 : bool bHangingPunct = rAttribs.getBool( XML_hangingPunct, false );
84 2024 : rPropertyMap.setProperty( PROP_ParaIsHangingPunctuation, bHangingPunct);
85 : }
86 :
87 : // ST_Coordinate
88 4838 : if ( rAttribs.hasAttribute( XML_indent ) )
89 : {
90 1105 : sValue = rAttribs.getString( XML_indent ).get();
91 1105 : mrTextParagraphProperties.getFirstLineIndentation() = boost::optional< sal_Int32 >( sValue.isEmpty() ? 0 : GetCoordinate( sValue ) );
92 : }
93 :
94 : // ST_TextIndentLevelType
95 : // -1 is an invalid value and denote the lack of level
96 4838 : sal_Int32 nLevel = rAttribs.getInteger( XML_lvl, 0 );
97 4838 : if( nLevel > 8 || nLevel < 0 )
98 : {
99 0 : nLevel = 0;
100 : }
101 :
102 4838 : mrTextParagraphProperties.setLevel( static_cast< sal_Int16 >( nLevel ) );
103 :
104 4838 : char name[] = "Outline X";
105 4838 : name[8] = static_cast<char>( '1' + nLevel );
106 9676 : const OUString sStyleNameValue( OUString::createFromAscii( name ) );
107 4838 : mrBulletList.setStyleName( sStyleNameValue );
108 :
109 : // ST_TextMargin
110 : // ParaLeftMargin
111 4838 : if ( rAttribs.hasAttribute( XML_marL ) )
112 : {
113 2505 : sValue = rAttribs.getString( XML_marL ).get();
114 2505 : mrTextParagraphProperties.getParaLeftMargin() = boost::optional< sal_Int32 >( sValue.isEmpty() ? 0 : GetCoordinate( sValue ) );
115 : }
116 :
117 : // ParaRightMargin
118 4838 : if ( rAttribs.hasAttribute( XML_marR ) )
119 : {
120 57 : sValue = rAttribs.getString( XML_marR ).get();
121 57 : sal_Int32 nMarR = sValue.isEmpty() ? 0 : GetCoordinate( sValue ) ;
122 57 : rPropertyMap.setProperty( PROP_ParaRightMargin, nMarR);
123 : }
124 :
125 4838 : if ( rAttribs.hasAttribute( XML_rtl ) )
126 : {
127 2196 : bool bRtl = rAttribs.getBool( XML_rtl, false );
128 2196 : rPropertyMap.setProperty( PROP_WritingMode, ( bRtl ? WritingMode2::RL_TB : WritingMode2::LR_TB ));
129 4838 : }
130 4838 : }
131 :
132 14514 : TextParagraphPropertiesContext::~TextParagraphPropertiesContext()
133 : {
134 4838 : PropertyMap& rPropertyMap( mrTextParagraphProperties.getTextParagraphPropertyMap() );
135 4838 : if ( maLineSpacing.bHasValue )
136 550 : rPropertyMap.setProperty( PROP_ParaLineSpacing, maLineSpacing.toLineSpacing());
137 : else
138 4288 : rPropertyMap.setProperty( PROP_ParaLineSpacing, ::com::sun::star::style::LineSpacing( ::com::sun::star::style::LineSpacingMode::PROP, 100 ));
139 :
140 4838 : ::std::list< TabStop >::size_type nTabCount = maTabList.size();
141 4838 : if( nTabCount != 0 )
142 : {
143 10 : Sequence< TabStop > aSeq( nTabCount );
144 10 : TabStop * aArray = aSeq.getArray();
145 : OSL_ENSURE( aArray != NULL, "sequence array is NULL" );
146 10 : ::std::copy( maTabList.begin(), maTabList.end(), aArray );
147 10 : rPropertyMap.setProperty( PROP_ParaTabStops, aSeq);
148 : }
149 :
150 4838 : if ( mxBlipProps.get() && mxBlipProps->mxGraphic.is() )
151 6 : mrBulletList.setGraphic( mxBlipProps->mxGraphic );
152 :
153 4838 : if( mrBulletList.is() )
154 1176 : rPropertyMap.setProperty( PROP_IsNumbering, sal_True);
155 4838 : sal_Int16 nLevel = mrTextParagraphProperties.getLevel();
156 4838 : rPropertyMap.setProperty( PROP_NumberingLevel, nLevel);
157 4838 : rPropertyMap.setProperty( PROP_NumberingIsNumber, sal_True);
158 :
159 4838 : if( mrTextParagraphProperties.getParaAdjust() )
160 3352 : rPropertyMap.setProperty( PROP_ParaAdjust, mrTextParagraphProperties.getParaAdjust().get());
161 9676 : }
162 :
163 8655 : ContextHandlerRef TextParagraphPropertiesContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
164 : {
165 8655 : Reference< XFastContextHandler > xRet;
166 8655 : switch( aElementToken )
167 : {
168 : case A_TOKEN( lnSpc ): // CT_TextSpacing
169 495 : return new TextSpacingContext( *this, maLineSpacing );
170 : case A_TOKEN( spcBef ): // CT_TextSpacing
171 1162 : return new TextSpacingContext( *this, mrTextParagraphProperties.getParaTopMargin() );
172 : case A_TOKEN( spcAft ): // CT_TextSpacing
173 713 : return new TextSpacingContext( *this, mrTextParagraphProperties.getParaBottomMargin() );
174 : // EG_TextBulletColor
175 : case A_TOKEN( buClrTx ): // CT_TextBulletColorFollowText ???
176 14 : mrBulletList.mbBulletColorFollowText <<= sal_True;
177 14 : break;
178 : case A_TOKEN( buClr ): // CT_Color
179 234 : return new ColorContext( *this, *mrBulletList.maBulletColorPtr );
180 : // EG_TextBulletSize
181 : case A_TOKEN( buSzTx ): // CT_TextBulletSizeFollowText
182 50 : mrBulletList.setBulletSize(100);
183 50 : break;
184 : case A_TOKEN( buSzPct ): // CT_TextBulletSizePercent
185 218 : mrBulletList.setBulletSize( static_cast<sal_Int16>( GetPercent( rAttribs.getString( XML_val ).get() ) / 1000 ) );
186 218 : break;
187 : case A_TOKEN( buSzPts ): // CT_TextBulletSizePoint
188 0 : mrBulletList.setBulletSize(0);
189 0 : mrBulletList.setFontSize( static_cast<sal_Int16>(GetTextSize( rAttribs.getString( XML_val ).get() ) ) );
190 0 : break;
191 :
192 : // EG_TextBulletTypeface
193 : case A_TOKEN( buFontTx ): // CT_TextBulletTypefaceFollowText
194 36 : mrBulletList.mbBulletFontFollowText <<= sal_True;
195 36 : break;
196 : case A_TOKEN( buFont ): // CT_TextFont
197 752 : mrBulletList.maBulletFont.setAttributes( rAttribs );
198 752 : break;
199 :
200 : // EG_TextBullet
201 : case A_TOKEN( buNone ): // CT_TextNoBullet
202 470 : mrBulletList.setNone();
203 470 : break;
204 : case A_TOKEN( buAutoNum ): // CT_TextAutonumberBullet
205 : {
206 : try {
207 21 : sal_Int32 nType = rAttribs.getToken( XML_type, 0 );
208 21 : sal_Int32 nStartAt = rAttribs.getInteger( XML_startAt, 1 );
209 21 : if( nStartAt > 32767 )
210 : {
211 0 : nStartAt = 32767;
212 : }
213 21 : else if( nStartAt < 1 )
214 : {
215 0 : nStartAt = 1;
216 : }
217 21 : mrBulletList.setStartAt( nStartAt );
218 21 : mrBulletList.setType( nType );
219 : }
220 0 : catch(SAXException& /* e */ )
221 : {
222 : OSL_TRACE("OOX: SAXException in XML_buAutoNum");
223 : }
224 21 : break;
225 : }
226 : case A_TOKEN( buChar ): // CT_TextCharBullet
227 : try {
228 :
229 679 : mrBulletList.setBulletChar( rAttribs.getString( XML_char ).get() );
230 679 : mrBulletList.setSuffixNone();
231 : }
232 0 : catch(SAXException& /* e */)
233 : {
234 : OSL_TRACE("OOX: SAXException in XML_buChar");
235 : }
236 679 : break;
237 : case A_TOKEN( buBlip ): // CT_TextBlipBullet
238 : {
239 6 : mxBlipProps.reset( new BlipFillProperties );
240 6 : return new BlipFillContext( *this, rAttribs, *mxBlipProps );
241 : }
242 : case A_TOKEN( tabLst ): // CT_TextTabStopList
243 67 : return new TextTabStopListContext( *this, maTabList );
244 : case A_TOKEN( defRPr ): // CT_TextCharacterProperties
245 3206 : return new TextCharacterPropertiesContext( *this, rAttribs, mrTextParagraphProperties.getTextCharacterProperties() );
246 : case W_TOKEN( jc ):
247 : {
248 63 : OptValue< OUString > oParaAdjust = rAttribs.getString( W_TOKEN(val) );
249 63 : if( oParaAdjust.has() && !oParaAdjust.get().isEmpty() )
250 : {
251 63 : const OUString& sParaAdjust = oParaAdjust.get();
252 63 : if( sParaAdjust == "left" )
253 0 : mrTextParagraphProperties.setParaAdjust(ParagraphAdjust_LEFT);
254 63 : else if ( sParaAdjust == "right" )
255 4 : mrTextParagraphProperties.setParaAdjust(ParagraphAdjust_RIGHT);
256 59 : else if ( sParaAdjust == "center" )
257 36 : mrTextParagraphProperties.setParaAdjust(ParagraphAdjust_CENTER);
258 23 : else if ( sParaAdjust == "both" )
259 2 : mrTextParagraphProperties.setParaAdjust(ParagraphAdjust_BLOCK);
260 63 : }
261 : }
262 63 : break;
263 : case W_TOKEN( spacing ):
264 : {
265 : // Spacing before
266 60 : if( !rAttribs.getBool(W_TOKEN(beforeAutospacing), false) )
267 : {
268 58 : OptValue<sal_Int32> oBefore = rAttribs.getInteger(W_TOKEN(before));
269 58 : if (oBefore.has())
270 : {
271 36 : TextSpacing& rSpacing = mrTextParagraphProperties.getParaTopMargin();
272 36 : rSpacing.nUnit = TextSpacing::POINTS;
273 36 : rSpacing.nValue = TWIPS_TO_MM(oBefore.get());
274 36 : rSpacing.bHasValue = true;
275 : }
276 : else
277 : {
278 22 : OptValue<sal_Int32> oBeforeLines = rAttribs.getInteger(W_TOKEN(beforeLines));
279 22 : if (oBeforeLines.has())
280 : {
281 2 : TextSpacing& rSpacing = mrTextParagraphProperties.getParaTopMargin();
282 2 : rSpacing.nUnit = TextSpacing::PERCENT;
283 2 : rSpacing.nValue = oBeforeLines.get() * MAX_PERCENT / 100;
284 2 : rSpacing.bHasValue = true;
285 : }
286 : }
287 : }
288 :
289 : // Spacing after
290 60 : if( !rAttribs.getBool(W_TOKEN(afterAutospacing), false) )
291 : {
292 58 : OptValue<sal_Int32> oAfter = rAttribs.getInteger(W_TOKEN(after));
293 58 : if (oAfter.has())
294 : {
295 43 : TextSpacing& rSpacing = mrTextParagraphProperties.getParaBottomMargin();
296 43 : rSpacing.nUnit = TextSpacing::POINTS;
297 43 : rSpacing.nValue = TWIPS_TO_MM(oAfter.get());
298 43 : rSpacing.bHasValue = true;
299 : }
300 : else
301 : {
302 15 : OptValue<sal_Int32> oAfterLines = rAttribs.getInteger(W_TOKEN(afterLines));
303 15 : if (oAfterLines.has())
304 : {
305 2 : TextSpacing& rSpacing = mrTextParagraphProperties.getParaBottomMargin();
306 2 : rSpacing.nUnit = TextSpacing::PERCENT;
307 2 : rSpacing.nValue = oAfterLines.get() * MAX_PERCENT / 100;
308 2 : rSpacing.bHasValue = true;
309 : }
310 : }
311 : }
312 :
313 : // Line spacing
314 60 : OptValue<OUString> oLineRule = rAttribs.getString(W_TOKEN(lineRule));
315 60 : OptValue<sal_Int32> oLineSpacing = rAttribs.getInteger(W_TOKEN(line));
316 60 : if (oLineSpacing.has())
317 : {
318 55 : if( !oLineRule.has() || oLineRule.get() == "auto" )
319 : {
320 52 : maLineSpacing.nUnit = TextSpacing::PERCENT;
321 52 : maLineSpacing.nValue = oLineSpacing.get() * MAX_PERCENT / 240;
322 : }
323 : else
324 : {
325 3 : maLineSpacing.nUnit = TextSpacing::POINTS;
326 3 : maLineSpacing.nValue = TWIPS_TO_MM(oLineSpacing.get());
327 : }
328 55 : maLineSpacing.bHasValue = true;
329 60 : }
330 : }
331 60 : break;
332 : default:
333 : SAL_WARN("oox", "TextParagraphPropertiesContext::onCreateContext: unhandled element: " << getBaseToken(aElementToken));
334 : }
335 2772 : return this;
336 : }
337 :
338 : } }
339 :
340 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|