nss: upgrade to release 3.73
[LibreOffice.git] / oox / source / vml / vmltextboxcontext.cxx
blobd878c6dcdf3d91fa4f137f886f3ee97369ebf341
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <oox/helper/attributelist.hxx>
21 #include <oox/vml/vmlformatting.hxx>
22 #include <oox/vml/vmltextboxcontext.hxx>
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>
29 namespace oox::vml {
31 using ::oox::core::ContextHandler2;
32 using ::oox::core::ContextHandler2Helper;
33 using ::oox::core::ContextHandlerRef;
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() )
44 switch( nElement )
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):
74 OptValue<OUString> oRelId = rAttribs.getString(R_TOKEN(embed));
75 if (oRelId.has())
76 mrTextBox.mrTypeModel.moGraphicPath = getFragmentPathFromRelId(oRelId.get());
78 break;
79 case VML_TOKEN(imagedata):
81 OptValue<OUString> oRelId = rAttribs.getString(R_TOKEN(id));
82 if (oRelId.has())
83 mrTextBox.mrTypeModel.moGraphicPath = getFragmentPathFromRelId(oRelId.get());
85 break;
86 case XML_span:
87 case W_TOKEN(r):
88 break;
89 default:
90 OSL_ENSURE( false, "TextPortionContext::TextPortionContext - unknown element" );
94 ContextHandlerRef TextPortionContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
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 );
102 void TextPortionContext::onCharacters( const OUString& rChars )
104 if (getNamespace(getCurrentElement()) == NMSP_doc && getCurrentElement() != W_TOKEN(t))
105 return;
107 switch( getCurrentElement() )
109 case XML_span:
110 // replace all NBSP characters with SP
111 mrTextBox.appendPortion( maParagraph, maFont, rChars.replace( 0xA0, ' ' ) );
112 break;
113 default:
114 mrTextBox.appendPortion( maParagraph, maFont, rChars );
118 void TextPortionContext::onStartElement(const AttributeList& rAttribs)
120 switch (getCurrentElement())
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):
129 mrTextBox.appendPortion( maParagraph, maFont, "\n" );
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;
153 void TextPortionContext::onEndElement()
155 if (getNamespace(getCurrentElement()) == NMSP_doc && getCurrentElement() != W_TOKEN(t))
156 return;
158 /* A child element without own child elements may contain a single space
159 character, for example:
161 <div>
162 <font><i>abc</i></font>
163 <font> </font>
164 <font><b>def</b></font>
165 </div>
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.
174 if( mrTextBox.getPortionCount() == mnInitialPortions )
175 mrTextBox.appendPortion( maParagraph, maFont, OUString( ' ' ) );
178 TextBoxContext::TextBoxContext( ContextHandler2Helper const & rParent, TextBox& rTextBox, const AttributeList& rAttribs,
179 const GraphicHelper& graphicHelper ) :
180 ContextHandler2( rParent ),
181 mrTextBox( rTextBox )
183 if( rAttribs.getString( XML_insetmode ).get() != "auto" )
185 OUString inset = rAttribs.getString( XML_inset ).get();
186 OUString value;
187 OUString remainingStr;
189 ConversionHelper::separatePair( value, remainingStr, inset, ',' );
190 rTextBox.borderDistanceLeft = ConversionHelper::decodeMeasureToHmm( graphicHelper,
191 value.isEmpty() ? "0.1in" : value, 0, false, false );
193 inset = remainingStr;
194 ConversionHelper::separatePair( value, remainingStr, inset, ',' );
195 rTextBox.borderDistanceTop = ConversionHelper::decodeMeasureToHmm( graphicHelper,
196 value.isEmpty() ? "0.05in" : value, 0, false, false );
198 inset = remainingStr;
199 ConversionHelper::separatePair( value, remainingStr, inset, ',' );
200 rTextBox.borderDistanceRight = ConversionHelper::decodeMeasureToHmm( graphicHelper,
201 value.isEmpty() ? "0.1in" : value, 0, false, false );
203 inset = remainingStr;
204 ConversionHelper::separatePair( value, remainingStr, inset, ',' );
205 rTextBox.borderDistanceBottom = ConversionHelper::decodeMeasureToHmm( graphicHelper,
206 value.isEmpty() ? "0.05in" : value, 0, false, false );
208 rTextBox.borderDistanceSet = true;
211 OUString sStyle = rAttribs.getString( XML_style, OUString() );
212 sal_Int32 nIndex = 0;
213 while( nIndex >= 0 )
215 OUString aName, aValue;
216 if( ConversionHelper::separatePair( aName, aValue, sStyle.getToken( 0, ';', nIndex ), ':' ) )
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);
231 ContextHandlerRef TextBoxContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
233 switch( getCurrentElement() )
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 break;
253 case W_TOKEN(pPr):
254 case W_TOKEN(sdt):
255 return this;
256 break;
257 default:
258 SAL_INFO("oox", "unhandled 0x" << std::hex << getCurrentElement());
259 break;
261 return nullptr;
264 void TextBoxContext::onStartElement(const AttributeList& rAttribs)
266 switch (getCurrentElement())
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;
277 void TextBoxContext::onEndElement()
279 if (getCurrentElement() == W_TOKEN(p))
281 mrTextBox.appendPortion( maParagraph, TextFontModel(), "\n" );
282 maParagraph = TextParagraphModel();
286 } // namespace oox::vml
288 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */