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