LibreOffice Module oox (master)  1
textparagraphpropertiescontext.cxx
Go to the documentation of this file.
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 
21 
22 #include <com/sun/star/text/WritingMode2.hpp>
23 #include <com/sun/star/style/ParagraphAdjust.hpp>
24 #include <com/sun/star/xml/sax/SAXException.hpp>
25 #include <com/sun/star/graphic/XGraphic.hpp>
26 #include <com/sun/star/awt/Size.hpp>
27 #include <com/sun/star/uno/Reference.hxx>
28 
29 #include <sal/log.hxx>
30 #include <tools/diagnose_ex.h>
31 #include <tools/UnitConversion.hxx>
32 
38 #include "textspacingcontext.hxx"
40 #include <oox/token/namespaces.hxx>
41 #include <oox/token/properties.hxx>
42 #include <oox/token/tokens.hxx>
43 
44 using namespace ::oox::core;
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::xml::sax;
47 using namespace ::com::sun::star::style;
48 using namespace ::com::sun::star::text;
49 using namespace ::com::sun::star::graphic;
50 
51 namespace oox::drawingml {
52 namespace {
53 
54 double lclGetGraphicAspectRatio( const Reference< XGraphic >& rxGraphic )
55 {
56  double fRatio = 1.0;
57  Reference< com::sun::star::beans::XPropertySet > xGraphicPropertySet( rxGraphic, UNO_QUERY_THROW );
58  css::awt::Size aSizeHmm( 0, 0 );
59  xGraphicPropertySet->getPropertyValue( "Size100thMM" ) >>= aSizeHmm;
60 
61  if( aSizeHmm.Width > 0 && aSizeHmm.Height > 0)
62  return double(aSizeHmm.Width)/double(aSizeHmm.Height);
63  else
64  {
65  css::awt::Size aSourceSizePixel( 0, 0 );
66  xGraphicPropertySet->getPropertyValue( "SizePixel" ) >>= aSourceSizePixel;
67 
68  if( aSourceSizePixel.Width > 0 && aSourceSizePixel.Height > 0 )
69  return double(aSourceSizePixel.Width)/double(aSourceSizePixel.Height);
70  }
71  return fRatio;
72 }
73 
74 } //namespace
75 
76 // CT_TextParagraphProperties
78  const AttributeList& rAttribs,
79  TextParagraphProperties& rTextParagraphProperties )
80 : ContextHandler2( rParent )
81 , mrTextParagraphProperties( rTextParagraphProperties )
82 , mrBulletList( rTextParagraphProperties.getBulletList() )
83 {
84  OUString sValue;
85 
87 
88  // ST_TextAlignType
89  if ( rAttribs.hasAttribute( XML_algn ) )
90  {
91  mrTextParagraphProperties.getParaAdjust() = GetParaAdjust( rAttribs.getToken( XML_algn, XML_l ) );
92  }
93  // TODO see to do the same with RubyAdjust
94 
95  // ST_Coordinate32
96 // sValue = rAttribs.getString( XML_defTabSz ).get(); SJ: we need to be able to set the default tab size for each text object,
97 // this is possible at the moment only for the whole document.
98 // sal_Int32 nDefTabSize = ( sValue.getLength() == 0 ? 0 : GetCoordinate( sValue ) );
99  // TODO
100 
101 // bool bEaLineBrk = rAttribs.getBool( XML_eaLnBrk, true );
102  if ( rAttribs.hasAttribute( XML_latinLnBrk ) )
103  {
104  bool bLatinLineBrk = rAttribs.getBool( XML_latinLnBrk, true );
105  rPropertyMap.setProperty( PROP_ParaIsHyphenation, bLatinLineBrk);
106  }
107  // TODO see what to do with Asian hyphenation
108 
109  // ST_TextFontAlignType
110  // TODO
111 // sal_Int32 nFontAlign = rAttribs.getToken( XML_fontAlgn, XML_base );
112 
113  if ( rAttribs.hasAttribute( XML_hangingPunct ) )
114  {
115  bool bHangingPunct = rAttribs.getBool( XML_hangingPunct, false );
116  rPropertyMap.setProperty( PROP_ParaIsHangingPunctuation, bHangingPunct);
117  }
118 
119  // ST_Coordinate
120  if ( rAttribs.hasAttribute( XML_indent ) )
121  {
122  sValue = rAttribs.getString( XML_indent ).get();
123  mrTextParagraphProperties.getFirstLineIndentation() = std::optional< sal_Int32 >( sValue.isEmpty() ? 0 : GetCoordinate( sValue ) );
124  }
125 
126  // ST_TextIndentLevelType
127  // -1 is an invalid value and denote the lack of level
128  sal_Int32 nLevel = rAttribs.getInteger( XML_lvl, 0 );
129  if( nLevel > 8 || nLevel < 0 )
130  {
131  nLevel = 0;
132  }
133 
134  mrTextParagraphProperties.setLevel( static_cast< sal_Int16 >( nLevel ) );
135 
136  char name[] = "Outline X";
137  name[8] = static_cast<char>( '1' + nLevel );
138  const OUString sStyleNameValue( OUString::createFromAscii( name ) );
139  mrBulletList.setStyleName( sStyleNameValue );
140 
141  // ST_TextMargin
142  // ParaLeftMargin
143  if ( rAttribs.hasAttribute( XML_marL ) )
144  {
145  sValue = rAttribs.getString( XML_marL ).get();
146  mrTextParagraphProperties.getParaLeftMargin() = std::optional< sal_Int32 >( sValue.isEmpty() ? 0 : GetCoordinate( sValue ) );
147  }
148 
149  // ParaRightMargin
150  if ( rAttribs.hasAttribute( XML_marR ) )
151  {
152  sValue = rAttribs.getString( XML_marR ).get();
153  sal_Int32 nMarR = sValue.isEmpty() ? 0 : GetCoordinate( sValue ) ;
154  rPropertyMap.setProperty( PROP_ParaRightMargin, nMarR);
155  }
156 
157  if ( rAttribs.hasAttribute( XML_rtl ) )
158  {
159  bool bRtl = rAttribs.getBool( XML_rtl, false );
160  rPropertyMap.setProperty( PROP_WritingMode, ( bRtl ? WritingMode2::RL_TB : WritingMode2::LR_TB ));
161  }
162 }
163 
165 {
168  rPropertyMap.setProperty( PROP_ParaLineSpacing, mrTextParagraphProperties.getLineSpacing().toLineSpacing());
169  else
170  rPropertyMap.setProperty( PROP_ParaLineSpacing, css::style::LineSpacing( css::style::LineSpacingMode::PROP, 100 ));
171 
172  ::std::vector< TabStop >::size_type nTabCount = maTabList.size();
173  if( nTabCount != 0 )
174  {
175  Sequence< TabStop > aSeq( nTabCount );
176  TabStop * aArray = aSeq.getArray();
177  OSL_ENSURE( aArray != nullptr, "sequence array is NULL" );
178  ::std::copy( maTabList.begin(), maTabList.end(), aArray );
179  rPropertyMap.setProperty( PROP_ParaTabStops, aSeq);
180  }
181 
182  if (mxBlipProps && mxBlipProps->mxFillGraphic.is())
183  {
184  mrBulletList.setGraphic( mxBlipProps->mxFillGraphic );
185  mrBulletList.setBulletAspectRatio( lclGetGraphicAspectRatio(mxBlipProps->mxFillGraphic) );
186  }
187 
188  if( mrBulletList.is() )
189  rPropertyMap.setProperty( PROP_IsNumbering, true);
190  sal_Int16 nLevel = mrTextParagraphProperties.getLevel();
191  rPropertyMap.setProperty( PROP_NumberingLevel, nLevel);
192  rPropertyMap.setProperty( PROP_NumberingIsNumber, true);
193 
195  rPropertyMap.setProperty( PROP_ParaAdjust, *mrTextParagraphProperties.getParaAdjust());
196 }
197 
199 {
200  switch( aElementToken )
201  {
202  case A_TOKEN( lnSpc ): // CT_TextSpacing
204  case A_TOKEN( spcBef ): // CT_TextSpacing
206  case A_TOKEN( spcAft ): // CT_TextSpacing
208  // EG_TextBulletColor
209  case A_TOKEN( buClrTx ): // CT_TextBulletColorFollowText ???
211  break;
212  case A_TOKEN( buClr ): // CT_Color
213  return new ColorContext( *this, *mrBulletList.maBulletColorPtr );
214  // EG_TextBulletSize
215  case A_TOKEN( buSzTx ): // CT_TextBulletSizeFollowText
217  break;
218  case A_TOKEN( buSzPct ): // CT_TextBulletSizePercent
219  mrBulletList.setBulletSize( std::lround( GetPercent( rAttribs.getString( XML_val ).get() ) / 1000.f ) );
220  break;
221  case A_TOKEN( buSzPts ): // CT_TextBulletSizePoint
223  mrBulletList.setFontSize( static_cast<sal_Int16>(GetTextSize( rAttribs.getString( XML_val ).get() ) ) );
224  break;
225 
226  // EG_TextBulletTypeface
227  case A_TOKEN( buFontTx ): // CT_TextBulletTypefaceFollowText
229  break;
230  case A_TOKEN( buFont ): // CT_TextFont
232  break;
233 
234  // EG_TextBullet
235  case A_TOKEN( buNone ): // CT_TextNoBullet
237  break;
238  case A_TOKEN( buAutoNum ): // CT_TextAutonumberBullet
239  {
240  try {
241  sal_Int32 nType = rAttribs.getToken( XML_type, 0 );
242  sal_Int32 nStartAt = rAttribs.getInteger( XML_startAt, 1 );
243  if( nStartAt > 32767 )
244  {
245  nStartAt = 32767;
246  }
247  else if( nStartAt < 1 )
248  {
249  nStartAt = 1;
250  }
251  mrBulletList.setStartAt( nStartAt );
252  mrBulletList.setType( nType );
253  }
254  catch(SAXException& /* e */ )
255  {
256  TOOLS_WARN_EXCEPTION("oox", "OOX: SAXException in XML_buAutoNum");
257  }
258  break;
259  }
260  case A_TOKEN( buChar ): // CT_TextCharBullet
261  try {
262 
263  mrBulletList.setBulletChar( rAttribs.getString( XML_char ).get() );
265  }
266  catch(SAXException& /* e */)
267  {
268  TOOLS_WARN_EXCEPTION("oox", "OOX: SAXException in XML_buChar");
269  }
270  break;
271  case A_TOKEN( buBlip ): // CT_TextBlipBullet
272  {
273  mxBlipProps = std::make_shared<BlipFillProperties>();
274  return new BlipFillContext( *this, rAttribs, *mxBlipProps );
275  }
276  case A_TOKEN( tabLst ): // CT_TextTabStopList
277  return new TextTabStopListContext( *this, maTabList );
278  case A_TOKEN( defRPr ): // CT_TextCharacterProperties
280  case W_TOKEN( jc ):
281  {
282  OptValue< OUString > oParaAdjust = rAttribs.getString( W_TOKEN(val) );
283  if( oParaAdjust.has() && !oParaAdjust.get().isEmpty() )
284  {
285  const OUString& sParaAdjust = oParaAdjust.get();
286  if( sParaAdjust == "left" )
287  mrTextParagraphProperties.setParaAdjust(ParagraphAdjust_LEFT);
288  else if ( sParaAdjust == "right" )
289  mrTextParagraphProperties.setParaAdjust(ParagraphAdjust_RIGHT);
290  else if ( sParaAdjust == "center" )
291  mrTextParagraphProperties.setParaAdjust(ParagraphAdjust_CENTER);
292  else if ( sParaAdjust == "both" )
293  mrTextParagraphProperties.setParaAdjust(ParagraphAdjust_BLOCK);
294  }
295  }
296  break;
297  case W_TOKEN( spacing ):
298  {
299  // Spacing before
300  if( !rAttribs.getBool(W_TOKEN(beforeAutospacing), false) )
301  {
302  OptValue<sal_Int32> oBefore = rAttribs.getInteger(W_TOKEN(before));
303  if (oBefore.has())
304  {
306  rSpacing.nUnit = TextSpacing::Unit::Points;
307  rSpacing.nValue = convertTwipToMm100(oBefore.get());
308  rSpacing.bHasValue = true;
309  }
310  else
311  {
312  OptValue<sal_Int32> oBeforeLines = rAttribs.getInteger(W_TOKEN(beforeLines));
313  if (oBeforeLines.has())
314  {
317  rSpacing.nValue = oBeforeLines.get() * MAX_PERCENT / 100;
318  rSpacing.bHasValue = true;
319  }
320  }
321  }
322 
323  // Spacing after
324  if( !rAttribs.getBool(W_TOKEN(afterAutospacing), false) )
325  {
326  OptValue<sal_Int32> oAfter = rAttribs.getInteger(W_TOKEN(after));
327  if (oAfter.has())
328  {
330  rSpacing.nUnit = TextSpacing::Unit::Points;
331  rSpacing.nValue = convertTwipToMm100(oAfter.get());
332  rSpacing.bHasValue = true;
333  }
334  else
335  {
336  OptValue<sal_Int32> oAfterLines = rAttribs.getInteger(W_TOKEN(afterLines));
337  if (oAfterLines.has())
338  {
341  rSpacing.nValue = oAfterLines.get() * MAX_PERCENT / 100;
342  rSpacing.bHasValue = true;
343  }
344  }
345  }
346 
347  // Line spacing
348  OptValue<OUString> oLineRule = rAttribs.getString(W_TOKEN(lineRule));
349  OptValue<sal_Int32> oLineSpacing = rAttribs.getInteger(W_TOKEN(line));
350  if (oLineSpacing.has())
351  {
353  if( !oLineRule.has() || oLineRule.get() == "auto" )
354  {
355  rLineSpacing.nUnit = TextSpacing::Unit::Percent;
356  rLineSpacing.nValue = oLineSpacing.get() * MAX_PERCENT / 240;
357  }
358  else
359  {
360  rLineSpacing.nUnit = TextSpacing::Unit::Points;
361  rLineSpacing.nValue = convertTwipToMm100(oLineSpacing.get());
362  }
363  rLineSpacing.bHasValue = true;
364  }
365  }
366  break;
367  default:
368  SAL_WARN("oox", "TextParagraphPropertiesContext::onCreateContext: unhandled element: " << getBaseToken(aElementToken));
369  }
370  return this;
371 }
372 
373 }
374 
375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
tuple line
Context handler that imports the a:blipFill element.
std::optional< css::style::ParagraphAdjust > & getParaAdjust()
A helper that maps property identifiers to property values.
Definition: propertymap.hxx:51
OptValue< bool > getBool(sal_Int32 nAttrToken) const
Returns the boolean value of the specified attribute.
OptValue< sal_Int32 > getInteger(sal_Int32 nAttrToken) const
Returns the 32-bit signed integer value of the specified attribute (decimal).
bool setProperty(sal_Int32 nPropId, Type &&rValue)
Sets the specified property to the passed value.
Definition: propertymap.hxx:72
css::style::LineSpacing toLineSpacing() const
Definition: textspacing.hxx:43
virtual ::oox::core::ContextHandlerRef onCreateContext(::sal_Int32 Element, const ::oox::AttributeList &rAttribs) override
carries a CT_TextSpacing
Definition: textspacing.hxx:31
OptValue< OUString > getString(sal_Int32 nAttrToken) const
Returns the string value of the specified attribute.
void setBulletChar(const OUString &sChar)
constexpr auto convertTwipToMm100(N n)
std::optional< sal_Int32 > & getFirstLineIndentation()
::oox::drawingml::TextFont maBulletFont
void setBulletAspectRatio(double nAspectRatio)
sal_Int32 GetPercent(std::u16string_view sValue)
converts a ST_Percentage % string into 1/1000th of %
bool hasAttribute(sal_Int32 nAttrToken) const
Returns true, if the specified attribute is present.
const Type & get() const
Definition: helper.hxx:185
#define TOOLS_WARN_EXCEPTION(area, stream)
void setStyleName(const OUString &rStyleName)
const sal_Int32 MAX_PERCENT
Context handler for elements that contain a color value element (a:scrgbClr, a:srgbClr, a:hslClr, a:sysClr, a:schemeClr, a:prstClr).
XML_type
void setAttributes(const AttributeList &rAttribs)
Sets attributes from the passed attribute list.
Definition: textfont.cxx:56
Provides access to attribute values of an element.
void setGraphic(css::uno::Reference< css::graphic::XGraphic > const &rXGraphic)
sal_Int32 GetCoordinate(sal_Int32 nValue)
converts EMUs into 1/100th mmm
void setStartAt(sal_Int32 nStartAt)
ParagraphAdjust GetParaAdjust(sal_Int32 nAlign)
converts a paragraph align to a ParaAdjust
std::optional< sal_Int32 > & getParaLeftMargin()
QPRO_FUNC_TYPE nType
const char * name
Sequence< sal_Int8 > aSeq
#define SAL_WARN(area, stream)
std::shared_ptr< ::oox::drawingml::Color > maBulletColorPtr
void(* f)(TrueTypeTable *)
TextCharacterProperties & getTextCharacterProperties()
Helper class that provides a context stack.
TextParagraphPropertiesContext(::oox::core::ContextHandler2Helper const &rParent, const ::oox::AttributeList &rAttributes, TextParagraphProperties &rTextParagraphProperties)
bool has() const
Definition: helper.hxx:181
float GetTextSize(std::u16string_view sValue)
converts the ST_TextFontSize to point
void setParaAdjust(css::style::ParagraphAdjust nParaAdjust)
OptValue< sal_Int32 > getToken(sal_Int32 nAttrToken) const
Returns the token identifier of the value of the specified attribute.