bump product version to 4.2.0.1
[LibreOffice.git] / oox / source / vml / vmltextboxcontext.cxx
blobfe53d7809a0857707ea344860c636d08c21f1f37
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/vml/vmlformatting.hxx"
21 #include "oox/vml/vmltextboxcontext.hxx"
22 #include "oox/vml/vmlshape.hxx"
23 #include <com/sun/star/drawing/XShape.hpp>
25 namespace oox {
26 namespace vml {
28 // ============================================================================
30 using ::oox::core::ContextHandler2;
31 using ::oox::core::ContextHandler2Helper;
32 using ::oox::core::ContextHandlerRef;
34 // ============================================================================
36 TextPortionContext::TextPortionContext( ContextHandler2Helper& rParent,
37 TextBox& rTextBox, TextParagraphModel& rParagraph, const TextFontModel& rParentFont,
38 sal_Int32 nElement, const AttributeList& rAttribs ) :
39 ContextHandler2( rParent ),
40 mrTextBox( rTextBox ),
41 maParagraph( rParagraph ),
42 maFont( rParentFont ),
43 mnInitialPortions( rTextBox.getPortionCount() )
45 switch( nElement )
47 case XML_font:
48 maFont.moName = rAttribs.getXString( XML_face );
49 maFont.moColor = rAttribs.getXString( XML_color );
50 maFont.monSize = rAttribs.getInteger( XML_size );
51 break;
52 case XML_u:
53 OSL_ENSURE( !maFont.monUnderline, "TextPortionContext::TextPortionContext - nested <u> elements" );
54 maFont.monUnderline = (rAttribs.getToken( XML_class, XML_TOKEN_INVALID ) == XML_font4) ? XML_double : XML_single;
55 break;
56 case XML_sub:
57 case XML_sup:
58 OSL_ENSURE( !maFont.monEscapement, "TextPortionContext::TextPortionContext - nested <sub> or <sup> elements" );
59 maFont.monEscapement = nElement;
60 break;
61 case XML_b:
62 OSL_ENSURE( !maFont.mobBold, "TextPortionContext::TextPortionContext - nested <b> elements" );
63 maFont.mobBold = true;
64 break;
65 case XML_i:
66 OSL_ENSURE( !maFont.mobItalic, "TextPortionContext::TextPortionContext - nested <i> elements" );
67 maFont.mobItalic = true;
68 break;
69 case XML_s:
70 OSL_ENSURE( !maFont.mobStrikeout, "TextPortionContext::TextPortionContext - nested <s> elements" );
71 maFont.mobStrikeout = true;
72 break;
73 case OOX_TOKEN(dml, blip):
75 OptValue<OUString> oRelId = rAttribs.getString(R_TOKEN(embed));
76 if (oRelId.has())
77 mrTextBox.mrTypeModel.moGraphicPath = getFragmentPathFromRelId(oRelId.get());
79 break;
80 case VML_TOKEN(imagedata):
82 OptValue<OUString> oRelId = rAttribs.getString(R_TOKEN(id));
83 if (oRelId.has())
84 mrTextBox.mrTypeModel.moGraphicPath = getFragmentPathFromRelId(oRelId.get());
86 break;
87 case XML_span:
88 case OOX_TOKEN(doc, r):
89 break;
90 default:
91 OSL_ENSURE( false, "TextPortionContext::TextPortionContext - unknown element" );
95 ContextHandlerRef TextPortionContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
97 OSL_ENSURE( nElement != XML_font, "TextPortionContext::onCreateContext - nested <font> elements" );
98 if (getNamespace(getCurrentElement()) == NMSP_doc)
99 return this;
100 return new TextPortionContext( *this, mrTextBox, maParagraph, maFont, nElement, rAttribs );
103 void TextPortionContext::onCharacters( const OUString& rChars )
105 if (getNamespace(getCurrentElement()) == NMSP_doc && getCurrentElement() != OOX_TOKEN(doc, t))
106 return;
108 switch( getCurrentElement() )
110 case XML_span:
111 // replace all NBSP characters with SP
112 mrTextBox.appendPortion( maParagraph, maFont, rChars.replace( 0xA0, ' ' ) );
113 break;
114 default:
115 mrTextBox.appendPortion( maParagraph, maFont, rChars );
119 void TextPortionContext::onStartElement(const AttributeList& rAttribs)
121 switch (getCurrentElement())
123 case OOX_TOKEN(doc, b):
124 maFont.mobBold = true;
125 break;
126 case OOX_TOKEN(doc, sz):
127 maFont.monSize = rAttribs.getInteger( OOX_TOKEN(doc, val) );
128 break;
129 case OOX_TOKEN(doc, br):
130 mrTextBox.appendPortion( maParagraph, maFont, "\n" );
131 break;
132 case OOX_TOKEN(doc, color):
133 maFont.moColor = rAttribs.getString( OOX_TOKEN(doc, val) );
134 break;
135 case OOX_TOKEN(doc, spacing):
136 maFont.monSpacing = rAttribs.getInteger(OOX_TOKEN(doc, val));
137 break;
138 case OOX_TOKEN(doc, r):
139 case OOX_TOKEN(doc, rPr):
140 case OOX_TOKEN(doc, t):
141 break;
142 default:
143 SAL_INFO("oox", "unhandled: 0x" << std::hex<< getCurrentElement());
144 break;
148 void TextPortionContext::onEndElement()
150 if (getNamespace(getCurrentElement()) == NMSP_doc && getCurrentElement() != OOX_TOKEN(doc, t))
151 return;
153 /* A child element without own child elements may contain a single space
154 character, for example:
156 <div>
157 <font><i>abc</i></font>
158 <font> </font>
159 <font><b>def</b></font>
160 </div>
162 represents the italic text 'abc', an unformatted space character, and
163 the bold text 'def'. Unfortunately, the XML parser skips the space
164 character without issuing a 'characters' event. The class member
165 'mnInitialPortions' contains the number of text portions existing when
166 this context has been constructed. If no text has been added in the
167 meantime, the space character has to be added manually.
169 if( mrTextBox.getPortionCount() == mnInitialPortions )
170 mrTextBox.appendPortion( maParagraph, maFont, OUString( ' ' ) );
173 // ============================================================================
175 TextBoxContext::TextBoxContext( ContextHandler2Helper& rParent, TextBox& rTextBox, const AttributeList& rAttribs,
176 const GraphicHelper& graphicHelper ) :
177 ContextHandler2( rParent ),
178 mrTextBox( rTextBox )
180 if( rAttribs.getString( XML_insetmode ).get() != "auto" )
182 OUString inset = rAttribs.getString( XML_inset ).get();
183 OUString value;
184 OUString remainingStr;
186 ConversionHelper::separatePair( value, remainingStr, inset, ',' );
187 rTextBox.borderDistanceLeft = ConversionHelper::decodeMeasureToHmm( graphicHelper,
188 value.isEmpty() ? "0.1in" : value, 0, false, false );
190 inset = remainingStr;
191 ConversionHelper::separatePair( value, remainingStr, inset, ',' );
192 rTextBox.borderDistanceTop = ConversionHelper::decodeMeasureToHmm( graphicHelper,
193 value.isEmpty() ? "0.05in" : value, 0, false, false );
195 inset = remainingStr;
196 ConversionHelper::separatePair( value, remainingStr, inset, ',' );
197 rTextBox.borderDistanceRight = ConversionHelper::decodeMeasureToHmm( graphicHelper,
198 value.isEmpty() ? "0.1in" : value, 0, false, false );
200 inset = remainingStr;
201 ConversionHelper::separatePair( value, remainingStr, inset, ',' );
202 rTextBox.borderDistanceBottom = ConversionHelper::decodeMeasureToHmm( graphicHelper,
203 value.isEmpty() ? "0.05in" : value, 0, false, false );
205 rTextBox.borderDistanceSet = true;
208 OUString sStyle = rAttribs.getString( XML_style, OUString() );
209 sal_Int32 nIndex = 0;
210 while( nIndex >= 0 )
212 OUString aName, aValue;
213 if( ConversionHelper::separatePair( aName, aValue, sStyle.getToken( 0, ';', nIndex ), ':' ) )
215 if( aName == "layout-flow" ) rTextBox.maLayoutFlow = aValue;
216 else if (aName == "mso-fit-shape-to-text")
217 rTextBox.mrTypeModel.mbAutoHeight = true;
218 else if (aName == "mso-layout-flow-alt")
219 rTextBox.mrTypeModel.maLayoutFlowAlt = aValue;
220 else
221 SAL_WARN("oox", "unhandled style property: " << aName);
226 ContextHandlerRef TextBoxContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
228 switch( getCurrentElement() )
230 case VML_TOKEN( textbox ):
231 if( nElement == XML_div ) return this;
232 else if (nElement == OOX_TOKEN(doc, txbxContent)) return this;
233 break;
234 case XML_div:
235 if( nElement == XML_font ) return new TextPortionContext( *this, mrTextBox, maParagraph, TextFontModel(), nElement, rAttribs );
236 break;
237 case OOX_TOKEN(doc, txbxContent):
238 if (nElement == OOX_TOKEN(doc, p)) return this;
239 break;
240 case OOX_TOKEN(doc, p):
241 case OOX_TOKEN(doc, sdtContent):
242 if (nElement == OOX_TOKEN(doc, r))
243 return new TextPortionContext( *this, mrTextBox, maParagraph, TextFontModel(), nElement, rAttribs );
244 else
245 return this;
246 break;
247 case OOX_TOKEN(doc, pPr):
248 case OOX_TOKEN(doc, sdt):
249 return this;
250 break;
251 default:
252 SAL_INFO("oox", "unhandled 0x" << std::hex << getCurrentElement());
253 break;
255 return 0;
258 void TextBoxContext::onStartElement(const AttributeList& rAttribs)
260 switch (getCurrentElement())
262 case OOX_TOKEN(doc, jc):
263 maParagraph.moParaAdjust = rAttribs.getString( OOX_TOKEN(doc, val) );
264 break;
268 void TextBoxContext::onEndElement()
270 if (getCurrentElement() == OOX_TOKEN(doc, p))
272 mrTextBox.appendPortion( maParagraph, TextFontModel(), "\n" );
273 maParagraph = TextParagraphModel();
277 // ============================================================================
279 } // namespace vml
280 } // namespace oox
282 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */