1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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() )
48 maFont
.moName
= rAttribs
.getXString( XML_face
);
49 maFont
.moColor
= rAttribs
.getXString( XML_color
);
50 maFont
.monSize
= rAttribs
.getInteger( XML_size
);
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
;
58 OSL_ENSURE( !maFont
.monEscapement
, "TextPortionContext::TextPortionContext - nested <sub> or <sup> elements" );
59 maFont
.monEscapement
= nElement
;
62 OSL_ENSURE( !maFont
.mobBold
, "TextPortionContext::TextPortionContext - nested <b> elements" );
63 maFont
.mobBold
= true;
66 OSL_ENSURE( !maFont
.mobItalic
, "TextPortionContext::TextPortionContext - nested <i> elements" );
67 maFont
.mobItalic
= true;
70 OSL_ENSURE( !maFont
.mobStrikeout
, "TextPortionContext::TextPortionContext - nested <s> elements" );
71 maFont
.mobStrikeout
= true;
73 case OOX_TOKEN(dml
, blip
):
75 OptValue
<OUString
> oRelId
= rAttribs
.getString(R_TOKEN(embed
));
77 mrTextBox
.mrTypeModel
.moGraphicPath
= getFragmentPathFromRelId(oRelId
.get());
80 case VML_TOKEN(imagedata
):
82 OptValue
<OUString
> oRelId
= rAttribs
.getString(R_TOKEN(id
));
84 mrTextBox
.mrTypeModel
.moGraphicPath
= getFragmentPathFromRelId(oRelId
.get());
88 case OOX_TOKEN(doc
, r
):
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
)
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
))
108 switch( getCurrentElement() )
111 // replace all NBSP characters with SP
112 mrTextBox
.appendPortion( maParagraph
, maFont
, rChars
.replace( 0xA0, ' ' ) );
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;
126 case OOX_TOKEN(doc
, sz
):
127 maFont
.monSize
= rAttribs
.getInteger( OOX_TOKEN(doc
, val
) );
129 case OOX_TOKEN(doc
, br
):
130 mrTextBox
.appendPortion( maParagraph
, maFont
, "\n" );
132 case OOX_TOKEN(doc
, color
):
133 maFont
.moColor
= rAttribs
.getString( OOX_TOKEN(doc
, val
) );
135 case OOX_TOKEN(doc
, spacing
):
136 maFont
.monSpacing
= rAttribs
.getInteger(OOX_TOKEN(doc
, val
));
138 case OOX_TOKEN(doc
, r
):
139 case OOX_TOKEN(doc
, rPr
):
140 case OOX_TOKEN(doc
, t
):
143 SAL_INFO("oox", "unhandled: 0x" << std::hex
<< getCurrentElement());
148 void TextPortionContext::onEndElement()
150 if (getNamespace(getCurrentElement()) == NMSP_doc
&& getCurrentElement() != OOX_TOKEN(doc
, t
))
153 /* A child element without own child elements may contain a single space
154 character, for example:
157 <font><i>abc</i></font>
159 <font><b>def</b></font>
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();
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;
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
;
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;
235 if( nElement
== XML_font
) return new TextPortionContext( *this, mrTextBox
, maParagraph
, TextFontModel(), nElement
, rAttribs
);
237 case OOX_TOKEN(doc
, txbxContent
):
238 if (nElement
== OOX_TOKEN(doc
, p
)) return this;
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
);
247 case OOX_TOKEN(doc
, pPr
):
248 case OOX_TOKEN(doc
, sdt
):
252 SAL_INFO("oox", "unhandled 0x" << std::hex
<< getCurrentElement());
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
) );
268 void TextBoxContext::onEndElement()
270 if (getCurrentElement() == OOX_TOKEN(doc
, p
))
272 mrTextBox
.appendPortion( maParagraph
, TextFontModel(), "\n" );
273 maParagraph
= TextParagraphModel();
277 // ============================================================================
282 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */