1*ca5ec200SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*ca5ec200SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*ca5ec200SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*ca5ec200SAndrew Rist  * distributed with this work for additional information
6*ca5ec200SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*ca5ec200SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*ca5ec200SAndrew Rist  * "License"); you may not use this file except in compliance
9*ca5ec200SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*ca5ec200SAndrew Rist  *
11*ca5ec200SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*ca5ec200SAndrew Rist  *
13*ca5ec200SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*ca5ec200SAndrew Rist  * software distributed under the License is distributed on an
15*ca5ec200SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ca5ec200SAndrew Rist  * KIND, either express or implied.  See the License for the
17*ca5ec200SAndrew Rist  * specific language governing permissions and limitations
18*ca5ec200SAndrew Rist  * under the License.
19*ca5ec200SAndrew Rist  *
20*ca5ec200SAndrew Rist  *************************************************************/
21*ca5ec200SAndrew Rist 
22*ca5ec200SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "oox/vml/vmltextboxcontext.hxx"
25cdf0e10cSrcweir 
26cdf0e10cSrcweir namespace oox {
27cdf0e10cSrcweir namespace vml {
28cdf0e10cSrcweir 
29cdf0e10cSrcweir // ============================================================================
30cdf0e10cSrcweir 
31cdf0e10cSrcweir using ::oox::core::ContextHandler2;
32cdf0e10cSrcweir using ::oox::core::ContextHandler2Helper;
33cdf0e10cSrcweir using ::oox::core::ContextHandlerRef;
34cdf0e10cSrcweir using ::rtl::OUString;
35cdf0e10cSrcweir 
36cdf0e10cSrcweir // ============================================================================
37cdf0e10cSrcweir 
TextPortionContext(ContextHandler2Helper & rParent,TextBox & rTextBox,const TextFontModel & rParentFont,sal_Int32 nElement,const AttributeList & rAttribs)38cdf0e10cSrcweir TextPortionContext::TextPortionContext( ContextHandler2Helper& rParent,
39cdf0e10cSrcweir         TextBox& rTextBox, const TextFontModel& rParentFont,
40cdf0e10cSrcweir         sal_Int32 nElement, const AttributeList& rAttribs ) :
41cdf0e10cSrcweir     ContextHandler2( rParent ),
42cdf0e10cSrcweir     mrTextBox( rTextBox ),
43cdf0e10cSrcweir     maFont( rParentFont ),
44cdf0e10cSrcweir     mnInitialPortions( rTextBox.getPortionCount() )
45cdf0e10cSrcweir {
46cdf0e10cSrcweir     switch( nElement )
47cdf0e10cSrcweir     {
48cdf0e10cSrcweir         case XML_font:
49cdf0e10cSrcweir             maFont.moName = rAttribs.getXString( XML_face );
50cdf0e10cSrcweir             maFont.moColor = rAttribs.getXString( XML_color );
51cdf0e10cSrcweir             maFont.monSize = rAttribs.getInteger( XML_size );
52cdf0e10cSrcweir         break;
53cdf0e10cSrcweir         case XML_u:
54cdf0e10cSrcweir             OSL_ENSURE( !maFont.monUnderline, "TextPortionContext::TextPortionContext - nested <u> elements" );
55cdf0e10cSrcweir             maFont.monUnderline = (rAttribs.getToken( XML_class, XML_TOKEN_INVALID ) == XML_font4) ? XML_double : XML_single;
56cdf0e10cSrcweir         break;
57cdf0e10cSrcweir         case XML_sub:
58cdf0e10cSrcweir         case XML_sup:
59cdf0e10cSrcweir             OSL_ENSURE( !maFont.monEscapement, "TextPortionContext::TextPortionContext - nested <sub> or <sup> elements" );
60cdf0e10cSrcweir             maFont.monEscapement = nElement;
61cdf0e10cSrcweir         break;
62cdf0e10cSrcweir         case XML_b:
63cdf0e10cSrcweir             OSL_ENSURE( !maFont.mobBold, "TextPortionContext::TextPortionContext - nested <b> elements" );
64cdf0e10cSrcweir             maFont.mobBold = true;
65cdf0e10cSrcweir         break;
66cdf0e10cSrcweir         case XML_i:
67cdf0e10cSrcweir             OSL_ENSURE( !maFont.mobItalic, "TextPortionContext::TextPortionContext - nested <i> elements" );
68cdf0e10cSrcweir             maFont.mobItalic = true;
69cdf0e10cSrcweir         break;
70cdf0e10cSrcweir         case XML_s:
71cdf0e10cSrcweir             OSL_ENSURE( !maFont.mobStrikeout, "TextPortionContext::TextPortionContext - nested <s> elements" );
72cdf0e10cSrcweir             maFont.mobStrikeout = true;
73cdf0e10cSrcweir         break;
74cdf0e10cSrcweir         case XML_span:
75cdf0e10cSrcweir         break;
76cdf0e10cSrcweir         default:
77cdf0e10cSrcweir             OSL_ENSURE( false, "TextPortionContext::TextPortionContext - unknown element" );
78cdf0e10cSrcweir     }
79cdf0e10cSrcweir }
80cdf0e10cSrcweir 
onCreateContext(sal_Int32 nElement,const AttributeList & rAttribs)81cdf0e10cSrcweir ContextHandlerRef TextPortionContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
82cdf0e10cSrcweir {
83cdf0e10cSrcweir     OSL_ENSURE( nElement != XML_font, "TextPortionContext::onCreateContext - nested <font> elements" );
84cdf0e10cSrcweir     return new TextPortionContext( *this, mrTextBox, maFont, nElement, rAttribs );
85cdf0e10cSrcweir }
86cdf0e10cSrcweir 
onCharacters(const OUString & rChars)87cdf0e10cSrcweir void TextPortionContext::onCharacters( const OUString& rChars )
88cdf0e10cSrcweir {
89cdf0e10cSrcweir     switch( getCurrentElement() )
90cdf0e10cSrcweir     {
91cdf0e10cSrcweir         case XML_span:
92cdf0e10cSrcweir             // replace all NBSP characters with SP
93cdf0e10cSrcweir             mrTextBox.appendPortion( maFont, rChars.replace( 0xA0, ' ' ) );
94cdf0e10cSrcweir         break;
95cdf0e10cSrcweir         default:
96cdf0e10cSrcweir             mrTextBox.appendPortion( maFont, rChars );
97cdf0e10cSrcweir     }
98cdf0e10cSrcweir }
99cdf0e10cSrcweir 
onEndElement()100cdf0e10cSrcweir void TextPortionContext::onEndElement()
101cdf0e10cSrcweir {
102cdf0e10cSrcweir     /*  A child element without own child elements may contain a single space
103cdf0e10cSrcweir         character, for example:
104cdf0e10cSrcweir 
105cdf0e10cSrcweir           <div>
106cdf0e10cSrcweir             <font><i>abc</i></font>
107cdf0e10cSrcweir             <font> </font>
108cdf0e10cSrcweir             <font><b>def</b></font>
109cdf0e10cSrcweir           </div>
110cdf0e10cSrcweir 
111cdf0e10cSrcweir         represents the italic text 'abc', an unformatted space character, and
112cdf0e10cSrcweir         the bold text 'def'. Unfortunately, the XML parser skips the space
113cdf0e10cSrcweir         character without issuing a 'characters' event. The class member
114cdf0e10cSrcweir         'mnInitialPortions' contains the number of text portions existing when
115cdf0e10cSrcweir         this context has been constructed. If no text has been added in the
116cdf0e10cSrcweir         meantime, the space character has to be added manually.
117cdf0e10cSrcweir      */
118cdf0e10cSrcweir     if( mrTextBox.getPortionCount() == mnInitialPortions )
119cdf0e10cSrcweir         mrTextBox.appendPortion( maFont, OUString( sal_Unicode( ' ' ) ) );
120cdf0e10cSrcweir }
121cdf0e10cSrcweir 
122cdf0e10cSrcweir // ============================================================================
123cdf0e10cSrcweir 
TextBoxContext(ContextHandler2Helper & rParent,TextBox & rTextBox,const AttributeList &)124cdf0e10cSrcweir TextBoxContext::TextBoxContext( ContextHandler2Helper& rParent, TextBox& rTextBox, const AttributeList& /*rAttribs*/ ) :
125cdf0e10cSrcweir     ContextHandler2( rParent ),
126cdf0e10cSrcweir     mrTextBox( rTextBox )
127cdf0e10cSrcweir {
128cdf0e10cSrcweir }
129cdf0e10cSrcweir 
onCreateContext(sal_Int32 nElement,const AttributeList & rAttribs)130cdf0e10cSrcweir ContextHandlerRef TextBoxContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
131cdf0e10cSrcweir {
132cdf0e10cSrcweir     switch( getCurrentElement() )
133cdf0e10cSrcweir     {
134cdf0e10cSrcweir         case VML_TOKEN( textbox ):
135cdf0e10cSrcweir             if( nElement == XML_div ) return this;
136cdf0e10cSrcweir         break;
137cdf0e10cSrcweir         case XML_div:
138cdf0e10cSrcweir             if( nElement == XML_font ) return new TextPortionContext( *this, mrTextBox, TextFontModel(), nElement, rAttribs );
139cdf0e10cSrcweir         break;
140cdf0e10cSrcweir     }
141cdf0e10cSrcweir     return 0;
142cdf0e10cSrcweir }
143cdf0e10cSrcweir 
144cdf0e10cSrcweir // ============================================================================
145cdf0e10cSrcweir 
146cdf0e10cSrcweir } // namespace vml
147cdf0e10cSrcweir } // namespace oox
148