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>
24 #include <osl/diagnose.h>
29 using ::oox::core::ContextHandler2
;
30 using ::oox::core::ContextHandler2Helper
;
31 using ::oox::core::ContextHandlerRef
;
33 TextPortionContext::TextPortionContext( ContextHandler2Helper
& rParent
,
34 TextBox
& rTextBox
, TextParagraphModel
& rParagraph
, const TextFontModel
& rParentFont
,
35 sal_Int32 nElement
, const AttributeList
& rAttribs
) :
36 ContextHandler2( rParent
),
37 mrTextBox( rTextBox
),
38 maParagraph( rParagraph
),
39 maFont( rParentFont
),
40 mnInitialPortions( rTextBox
.getPortionCount() )
45 maFont
.moName
= rAttribs
.getXString( XML_face
);
46 maFont
.moColor
= rAttribs
.getXString( XML_color
);
47 maFont
.monSize
= rAttribs
.getInteger( XML_size
);
50 OSL_ENSURE( !maFont
.monUnderline
, "TextPortionContext::TextPortionContext - nested <u> elements" );
51 maFont
.monUnderline
= (rAttribs
.getToken( XML_class
, XML_TOKEN_INVALID
) == XML_font4
) ? XML_double
: XML_single
;
55 OSL_ENSURE( !maFont
.monEscapement
, "TextPortionContext::TextPortionContext - nested <sub> or <sup> elements" );
56 maFont
.monEscapement
= nElement
;
59 OSL_ENSURE( !maFont
.mobBold
, "TextPortionContext::TextPortionContext - nested <b> elements" );
60 maFont
.mobBold
= true;
63 OSL_ENSURE( !maFont
.mobItalic
, "TextPortionContext::TextPortionContext - nested <i> elements" );
64 maFont
.mobItalic
= true;
67 OSL_ENSURE( !maFont
.mobStrikeout
, "TextPortionContext::TextPortionContext - nested <s> elements" );
68 maFont
.mobStrikeout
= true;
70 case OOX_TOKEN(dml
, blip
):
72 OptValue
<OUString
> oRelId
= rAttribs
.getString(R_TOKEN(embed
));
74 mrTextBox
.mrTypeModel
.moGraphicPath
= getFragmentPathFromRelId(oRelId
.get());
77 case VML_TOKEN(imagedata
):
79 OptValue
<OUString
> oRelId
= rAttribs
.getString(R_TOKEN(id
));
81 mrTextBox
.mrTypeModel
.moGraphicPath
= getFragmentPathFromRelId(oRelId
.get());
88 OSL_ENSURE( false, "TextPortionContext::TextPortionContext - unknown element" );
92 ContextHandlerRef
TextPortionContext::onCreateContext( sal_Int32 nElement
, const AttributeList
& rAttribs
)
94 OSL_ENSURE( nElement
!= XML_font
, "TextPortionContext::onCreateContext - nested <font> elements" );
95 if (getNamespace(getCurrentElement()) == NMSP_doc
)
97 return new TextPortionContext( *this, mrTextBox
, maParagraph
, maFont
, nElement
, rAttribs
);
100 void TextPortionContext::onCharacters( const OUString
& rChars
)
102 if (getNamespace(getCurrentElement()) == NMSP_doc
&& getCurrentElement() != W_TOKEN(t
))
105 switch( getCurrentElement() )
108 // replace all NBSP characters with SP
109 mrTextBox
.appendPortion( maParagraph
, maFont
, rChars
.replace( 0xA0, ' ' ) );
112 mrTextBox
.appendPortion( maParagraph
, maFont
, rChars
);
116 void TextPortionContext::onStartElement(const AttributeList
& rAttribs
)
118 switch (getCurrentElement())
121 maFont
.mobBold
= true;
124 maFont
.monSize
= rAttribs
.getInteger( W_TOKEN(val
) );
127 mrTextBox
.appendPortion( maParagraph
, maFont
, "\n" );
130 maFont
.moColor
= rAttribs
.getString( W_TOKEN(val
) );
132 case W_TOKEN(spacing
):
133 maFont
.monSpacing
= rAttribs
.getInteger(W_TOKEN(val
));
140 SAL_INFO("oox", "unhandled: 0x" << std::hex
<< getCurrentElement());
145 void TextPortionContext::onEndElement()
147 if (getNamespace(getCurrentElement()) == NMSP_doc
&& getCurrentElement() != W_TOKEN(t
))
150 /* A child element without own child elements may contain a single space
151 character, for example:
154 <font><i>abc</i></font>
156 <font><b>def</b></font>
159 represents the italic text 'abc', an unformatted space character, and
160 the bold text 'def'. Unfortunately, the XML parser skips the space
161 character without issuing a 'characters' event. The class member
162 'mnInitialPortions' contains the number of text portions existing when
163 this context has been constructed. If no text has been added in the
164 meantime, the space character has to be added manually.
166 if( mrTextBox
.getPortionCount() == mnInitialPortions
)
167 mrTextBox
.appendPortion( maParagraph
, maFont
, OUString( ' ' ) );
170 TextBoxContext::TextBoxContext( ContextHandler2Helper
& rParent
, TextBox
& rTextBox
, const AttributeList
& rAttribs
,
171 const GraphicHelper
& graphicHelper
) :
172 ContextHandler2( rParent
),
173 mrTextBox( rTextBox
)
175 if( rAttribs
.getString( XML_insetmode
).get() != "auto" )
177 OUString inset
= rAttribs
.getString( XML_inset
).get();
179 OUString remainingStr
;
181 ConversionHelper::separatePair( value
, remainingStr
, inset
, ',' );
182 rTextBox
.borderDistanceLeft
= ConversionHelper::decodeMeasureToHmm( graphicHelper
,
183 value
.isEmpty() ? "0.1in" : value
, 0, false, false );
185 inset
= remainingStr
;
186 ConversionHelper::separatePair( value
, remainingStr
, inset
, ',' );
187 rTextBox
.borderDistanceTop
= ConversionHelper::decodeMeasureToHmm( graphicHelper
,
188 value
.isEmpty() ? "0.05in" : value
, 0, false, false );
190 inset
= remainingStr
;
191 ConversionHelper::separatePair( value
, remainingStr
, inset
, ',' );
192 rTextBox
.borderDistanceRight
= ConversionHelper::decodeMeasureToHmm( graphicHelper
,
193 value
.isEmpty() ? "0.1in" : value
, 0, false, false );
195 inset
= remainingStr
;
196 ConversionHelper::separatePair( value
, remainingStr
, inset
, ',' );
197 rTextBox
.borderDistanceBottom
= ConversionHelper::decodeMeasureToHmm( graphicHelper
,
198 value
.isEmpty() ? "0.05in" : value
, 0, false, false );
200 rTextBox
.borderDistanceSet
= true;
203 OUString sStyle
= rAttribs
.getString( XML_style
, OUString() );
204 sal_Int32 nIndex
= 0;
207 OUString aName
, aValue
;
208 if( ConversionHelper::separatePair( aName
, aValue
, sStyle
.getToken( 0, ';', nIndex
), ':' ) )
210 if( aName
== "layout-flow" ) rTextBox
.maLayoutFlow
= aValue
;
211 else if (aName
== "mso-fit-shape-to-text")
212 rTextBox
.mrTypeModel
.mbAutoHeight
= true;
213 else if (aName
== "mso-layout-flow-alt")
214 rTextBox
.mrTypeModel
.maLayoutFlowAlt
= aValue
;
215 else if (aName
== "mso-next-textbox")
216 rTextBox
.msNextTextbox
= aValue
;
218 SAL_WARN("oox", "unhandled style property: " << aName
);
223 ContextHandlerRef
TextBoxContext::onCreateContext( sal_Int32 nElement
, const AttributeList
& rAttribs
)
225 switch( getCurrentElement() )
227 case VML_TOKEN( textbox
):
228 if( nElement
== XML_div
) return this;
229 else if (nElement
== W_TOKEN(txbxContent
)) return this;
232 if( nElement
== XML_font
) return new TextPortionContext( *this, mrTextBox
, maParagraph
, TextFontModel(), nElement
, rAttribs
);
234 case W_TOKEN(txbxContent
):
235 if (nElement
== W_TOKEN(p
)) return this;
238 case W_TOKEN(sdtContent
):
239 case W_TOKEN(smartTag
):
240 if (nElement
== W_TOKEN(r
))
241 return new TextPortionContext( *this, mrTextBox
, maParagraph
, TextFontModel(), nElement
, rAttribs
);
250 SAL_INFO("oox", "unhandled 0x" << std::hex
<< getCurrentElement());
256 void TextBoxContext::onStartElement(const AttributeList
& rAttribs
)
258 switch (getCurrentElement())
261 maParagraph
.moParaAdjust
= rAttribs
.getString( W_TOKEN(val
) );
266 void TextBoxContext::onEndElement()
268 if (getCurrentElement() == W_TOKEN(p
))
270 mrTextBox
.appendPortion( maParagraph
, TextFontModel(), "\n" );
271 maParagraph
= TextParagraphModel();
278 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */