LibreOffice Module oox (master)  1
vmltextboxcontext.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 
23 #include <oox/vml/vmlshape.hxx>
24 #include <oox/token/namespaces.hxx>
25 #include <oox/token/tokens.hxx>
26 #include <osl/diagnose.h>
27 #include <sal/log.hxx>
28 
29 namespace oox::vml {
30 
31 using ::oox::core::ContextHandler2;
32 using ::oox::core::ContextHandler2Helper;
34 
35 TextPortionContext::TextPortionContext( ContextHandler2Helper const & rParent,
36  TextBox& rTextBox, TextParagraphModel const & rParagraph, const TextFontModel& rParentFont,
37  sal_Int32 nElement, const AttributeList& rAttribs ) :
38  ContextHandler2( rParent ),
39  mrTextBox( rTextBox ),
40  maParagraph( rParagraph ),
41  maFont( rParentFont ),
42  mnInitialPortions( rTextBox.getPortionCount() )
43 {
44  switch( nElement )
45  {
46  case XML_font:
47  maFont.moName = rAttribs.getXString( XML_face );
48  maFont.moColor = rAttribs.getXString( XML_color );
49  maFont.monSize = rAttribs.getInteger( XML_size );
50  break;
51  case XML_u:
52  OSL_ENSURE( !maFont.monUnderline, "TextPortionContext::TextPortionContext - nested <u> elements" );
53  maFont.monUnderline = (rAttribs.getToken( XML_class, XML_TOKEN_INVALID ) == XML_font4) ? XML_double : XML_single;
54  break;
55  case XML_sub:
56  case XML_sup:
57  OSL_ENSURE( !maFont.monEscapement, "TextPortionContext::TextPortionContext - nested <sub> or <sup> elements" );
58  maFont.monEscapement = nElement;
59  break;
60  case XML_b:
61  OSL_ENSURE( !maFont.mobBold, "TextPortionContext::TextPortionContext - nested <b> elements" );
62  maFont.mobBold = true;
63  break;
64  case XML_i:
65  OSL_ENSURE( !maFont.mobItalic, "TextPortionContext::TextPortionContext - nested <i> elements" );
66  maFont.mobItalic = true;
67  break;
68  case XML_s:
69  OSL_ENSURE( !maFont.mobStrikeout, "TextPortionContext::TextPortionContext - nested <s> elements" );
70  maFont.mobStrikeout = true;
71  break;
72  case OOX_TOKEN(dml, blip):
73  {
74  OptValue<OUString> oRelId = rAttribs.getString(R_TOKEN(embed));
75  if (oRelId.has())
77  }
78  break;
79  case VML_TOKEN(imagedata):
80  {
81  OptValue<OUString> oRelId = rAttribs.getString(R_TOKEN(id));
82  if (oRelId.has())
84  }
85  break;
86  case XML_span:
87  case W_TOKEN(r):
88  break;
89  default:
90  OSL_ENSURE( false, "TextPortionContext::TextPortionContext - unknown element" );
91  }
92 }
93 
95 {
96  OSL_ENSURE( nElement != XML_font, "TextPortionContext::onCreateContext - nested <font> elements" );
97  if (getNamespace(getCurrentElement()) == NMSP_doc)
98  return this;
99  return new TextPortionContext( *this, mrTextBox, maParagraph, maFont, nElement, rAttribs );
100 }
101 
102 void TextPortionContext::onCharacters( const OUString& rChars )
103 {
104  if (getNamespace(getCurrentElement()) == NMSP_doc && getCurrentElement() != W_TOKEN(t))
105  return;
106 
107  switch( getCurrentElement() )
108  {
109  case XML_span:
110  // replace all NBSP characters with SP
111  mrTextBox.appendPortion( maParagraph, maFont, rChars.replace( 0xA0, ' ' ) );
112  break;
113  default:
115  }
116 }
117 
119 {
120  switch (getCurrentElement())
121  {
122  case W_TOKEN(b):
123  maFont.mobBold = true;
124  break;
125  case W_TOKEN(sz):
126  maFont.monSize = rAttribs.getInteger( W_TOKEN(val) );
127  break;
128  case W_TOKEN(br):
130  break;
131  case W_TOKEN(color):
132  maFont.moColor = rAttribs.getString( W_TOKEN(val) );
133  break;
134  case W_TOKEN(spacing):
135  maFont.monSpacing = rAttribs.getInteger(W_TOKEN(val));
136  break;
137  case W_TOKEN(r):
138  case W_TOKEN(rPr):
139  case W_TOKEN(t):
140  break;
141  case W_TOKEN(rFonts):
142  // See https://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing.runfonts(v=office.14).aspx
143  maFont.moName = rAttribs.getString(W_TOKEN(ascii));
144  maFont.moNameAsian = rAttribs.getString(W_TOKEN(eastAsia));
145  maFont.moNameComplex = rAttribs.getString(W_TOKEN(cs));
146  break;
147  default:
148  SAL_INFO("oox", "unhandled: 0x" << std::hex<< getCurrentElement());
149  break;
150  }
151 }
152 
154 {
155  if (getNamespace(getCurrentElement()) == NMSP_doc && getCurrentElement() != W_TOKEN(t))
156  return;
157 
158  /* A child element without own child elements may contain a single space
159  character, for example:
160 
161  <div>
162  <font><i>abc</i></font>
163  <font> </font>
164  <font><b>def</b></font>
165  </div>
166 
167  represents the italic text 'abc', an unformatted space character, and
168  the bold text 'def'. Unfortunately, the XML parser skips the space
169  character without issuing a 'characters' event. The class member
170  'mnInitialPortions' contains the number of text portions existing when
171  this context has been constructed. If no text has been added in the
172  meantime, the space character has to be added manually.
173  */
175  mrTextBox.appendPortion( maParagraph, maFont, OUString( ' ' ) );
176 }
177 
178 TextBoxContext::TextBoxContext( ContextHandler2Helper const & rParent, TextBox& rTextBox, const AttributeList& rAttribs,
179  const GraphicHelper& graphicHelper ) :
180  ContextHandler2( rParent ),
181  mrTextBox( rTextBox )
182 {
183  if( rAttribs.getString( XML_insetmode ).get() != "auto" )
184  {
185  OUString inset = rAttribs.getString( XML_inset ).get();
186  OUString value;
187  OUString remainingStr;
188 
189  ConversionHelper::separatePair( value, remainingStr, inset, ',' );
191  value.isEmpty() ? "0.1in" : value, 0, false, false );
192 
193  inset = remainingStr;
194  ConversionHelper::separatePair( value, remainingStr, inset, ',' );
196  value.isEmpty() ? "0.05in" : value, 0, false, false );
197 
198  inset = remainingStr;
199  ConversionHelper::separatePair( value, remainingStr, inset, ',' );
201  value.isEmpty() ? "0.1in" : value, 0, false, false );
202 
203  inset = remainingStr;
204  ConversionHelper::separatePair( value, remainingStr, inset, ',' );
206  value.isEmpty() ? "0.05in" : value, 0, false, false );
207 
208  rTextBox.borderDistanceSet = true;
209  }
210 
211  OUString sStyle = rAttribs.getString( XML_style, OUString() );
212  sal_Int32 nIndex = 0;
213  while( nIndex >= 0 )
214  {
215  OUString aName, aValue;
216  if( ConversionHelper::separatePair( aName, aValue, sStyle.getToken( 0, ';', nIndex ), ':' ) )
217  {
218  if( aName == "layout-flow" ) rTextBox.maLayoutFlow = aValue;
219  else if (aName == "mso-fit-shape-to-text")
220  rTextBox.mrTypeModel.mbAutoHeight = true;
221  else if (aName == "mso-layout-flow-alt")
222  rTextBox.mrTypeModel.maLayoutFlowAlt = aValue;
223  else if (aName == "mso-next-textbox")
224  rTextBox.msNextTextbox = aValue;
225  else
226  SAL_WARN("oox", "unhandled style property: " << aName);
227  }
228  }
229 }
230 
232 {
233  switch( getCurrentElement() )
234  {
235  case VML_TOKEN( textbox ):
236  if( nElement == XML_div ) return this;
237  else if (nElement == W_TOKEN(txbxContent)) return this;
238  break;
239  case XML_div:
240  if( nElement == XML_font ) return new TextPortionContext( *this, mrTextBox, maParagraph, TextFontModel(), nElement, rAttribs );
241  break;
242  case W_TOKEN(txbxContent):
243  if (nElement == W_TOKEN(p)) return this;
244  break;
245  case W_TOKEN(p):
246  case W_TOKEN(sdtContent):
247  case W_TOKEN(smartTag):
248  if (nElement == W_TOKEN(r))
249  return new TextPortionContext( *this, mrTextBox, maParagraph, TextFontModel(), nElement, rAttribs );
250  else
251  return this;
252  case W_TOKEN(pPr):
253  case W_TOKEN(sdt):
254  return this;
255  default:
256  SAL_INFO("oox", "unhandled 0x" << std::hex << getCurrentElement());
257  break;
258  }
259  return nullptr;
260 }
261 
263 {
264  switch (getCurrentElement())
265  {
266  case W_TOKEN(jc):
267  maParagraph.moParaAdjust = rAttribs.getString( W_TOKEN(val) );
268  break;
269  case W_TOKEN(pStyle):
270  maParagraph.moParaStyleName = rAttribs.getString( W_TOKEN(val) );
271  break;
272  }
273 }
274 
276 {
277  if (getCurrentElement() == W_TOKEN(p))
278  {
281  }
282 }
283 
284 } // namespace oox::vml
285 
286 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Provides helper functions for colors, device measurement conversion, graphics, and graphic objects ha...
OptValue< OUString > moParaAdjust
Paragraph adjust (left, center, right, etc.)
Definition: vmltextbox.hxx:44
OOX_DLLPUBLIC sal_Int32 decodeMeasureToHmm(const GraphicHelper &rGraphicHelper, const OUString &rValue, sal_Int32 nRefValue, bool bPixelX, bool bDefaultAsPixel)
Converts the passed VML measure string to 1/100 mm.
A text paragraph in a textbox.
Definition: vmltextbox.hxx:42
sal_Int32 nIndex
#define ascii(x)
void appendPortion(const TextParagraphModel &rParagraph, const TextFontModel &rFont, const OUString &rText)
Appends a new text portion to the textbox.
Definition: vmltextbox.cxx:59
virtual void onStartElement(const AttributeList &rAttribs) override
Will be called when a new element has been started.
OptValue< sal_Int32 > monSpacing
Definition: vmltextbox.hxx:61
OptValue< OUString > getXString(sal_Int32 nAttrToken) const
Returns the string 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).
exports com.sun.star. embed
OptValue< OUString > moNameAsian
Asian font name.
Definition: vmltextbox.hxx:52
Font settings for a text portion in a textbox.
Definition: vmltextbox.hxx:49
OptValue< OUString > getString(sal_Int32 nAttrToken) const
Returns the string value of the specified attribute.
OptValue< bool > mobBold
Definition: vmltextbox.hxx:58
const Type & get() const
Definition: helper.hxx:185
virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, const AttributeList &rAttribs) override
Will be called to create a context handler for the passed element.
ShapeTypeModel & mrTypeModel
Definition: vmltextbox.hxx:95
virtual void onEndElement() override
Will be called when the current element is about to be left.
OOX_DLLPUBLIC bool separatePair(OUString &orValue1, OUString &orValue2, const OUString &rValue, sal_Unicode cSep)
Returns two values contained in rValue separated by cSep.
The textbox contains all text contents and properties.
Definition: vmltextbox.hxx:79
size_t getPortionCount() const
Returns the current number of text portions.
Definition: vmltextbox.hxx:88
OptValue< sal_Int32 > monUnderline
Single or double underline.
Definition: vmltextbox.hxx:56
sal_Int32 getCurrentElement() const
Returns the identifier of the currently processed element.
bool borderDistanceSet
Text distance from the border (inset attribute of v:textbox), valid only if set.
Definition: vmltextbox.hxx:97
XML_TOKEN_INVALID
OUString getFragmentPathFromRelId(const OUString &rRelId) const
Returns the full fragment path for the passed relation identifier.
OptValue< OUString > moParaStyleName
Definition: vmltextbox.hxx:45
OUString maLayoutFlow
Definition: vmltextbox.hxx:99
Provides access to attribute values of an element.
TextBoxContext(::oox::core::ContextHandler2Helper const &rParent, TextBox &rTextBox, const AttributeList &rAttribs, const GraphicHelper &graphicHelper)
XPropertyListType t
OptValue< sal_Int32 > monEscapement
Subscript or superscript.
Definition: vmltextbox.hxx:57
OptValue< OUString > moGraphicPath
Path to a graphic for this shape.
Definition: vmlshape.hxx:99
OptValue< OUString > moColor
Font color, HTML encoded, sort of.
Definition: vmltextbox.hxx:54
virtual void onStartElement(const AttributeList &rAttribs) override
Will be called when a new element has been started.
OptValue< OUString > moName
Font name.
Definition: vmltextbox.hxx:51
#define SAL_INFO(area, stream)
OUString aName
OptValue< OUString > moNameComplex
Complex font name.
Definition: vmltextbox.hxx:53
::rtl::Reference< ContextHandler > ContextHandlerRef
OptValue< sal_Int32 > monSize
Font size in twips.
Definition: vmltextbox.hxx:55
void * p
virtual void onEndElement() override
Will be called when the current element is about to be left.
Any value
TextParagraphModel maParagraph
OUString msNextTextbox
Definition: vmltextbox.hxx:100
TextPortionContext(::oox::core::ContextHandler2Helper const &rParent, TextBox &rTextBox, TextParagraphModel const &rParagraph, const TextFontModel &rParentFont, sal_Int32 nElement, const AttributeList &rAttribs)
#define SAL_WARN(area, stream)
virtual void onCharacters(const OUString &rChars) override
Will be called before a new child element starts, or if the current element is about to be left...
OUString maLayoutFlowAlt
Specifies the alternate layout flow for text in textboxes.
Definition: vmlshape.hxx:114
bool has() const
Definition: helper.hxx:181
bool mbAutoHeight
If true, the height value is a minimum value (mostly used for textboxes)
Definition: vmlshape.hxx:87
virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, const AttributeList &rAttribs) override
Will be called to create a context handler for the passed element.
OptValue< bool > mobStrikeout
Definition: vmltextbox.hxx:60
OptValue< sal_Int32 > getToken(sal_Int32 nAttrToken) const
Returns the token identifier of the value of the specified attribute.
OptValue< bool > mobItalic
Definition: vmltextbox.hxx:59