Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
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 .
18 : : */
19 : :
20 : : #include "oox/vml/vmlshapecontext.hxx"
21 : :
22 : : #include "oox/vml/vmldrawing.hxx"
23 : : #include "oox/vml/vmlshape.hxx"
24 : : #include "oox/vml/vmlshapecontainer.hxx"
25 : : #include "oox/vml/vmltextboxcontext.hxx"
26 : :
27 : : namespace oox {
28 : : namespace vml {
29 : :
30 : : // ============================================================================
31 : :
32 : : using namespace ::com::sun::star::awt;
33 : :
34 : : using ::oox::core::ContextHandler2;
35 : : using ::oox::core::ContextHandler2Helper;
36 : : using ::oox::core::ContextHandlerRef;
37 : : using ::rtl::OUString;
38 : :
39 : : // ============================================================================
40 : :
41 : : namespace {
42 : :
43 : : /** Returns the boolean value from the specified VML attribute (if present).
44 : : */
45 : 306 : OptValue< bool > lclDecodeBool( const AttributeList& rAttribs, sal_Int32 nToken )
46 : : {
47 [ + - ]: 306 : OptValue< OUString > oValue = rAttribs.getString( nToken );
48 [ + + ][ + - ]: 306 : if( oValue.has() ) return OptValue< bool >( ConversionHelper::decodeBool( oValue.get() ) );
49 : 306 : return OptValue< bool >();
50 : : }
51 : :
52 : : /** Returns the percentage value from the specified VML attribute (if present).
53 : : The value will be normalized (1.0 is returned for 100%).
54 : : */
55 : 51 : OptValue< double > lclDecodePercent( const AttributeList& rAttribs, sal_Int32 nToken, double fDefValue )
56 : : {
57 [ + - ]: 51 : OptValue< OUString > oValue = rAttribs.getString( nToken );
58 [ - + ][ # # ]: 51 : if( oValue.has() ) return OptValue< double >( ConversionHelper::decodePercent( oValue.get(), fDefValue ) );
59 : 51 : return OptValue< double >();
60 : : }
61 : :
62 : : /** Returns the integer value pair from the specified VML attribute (if present).
63 : : */
64 : 174 : OptValue< Int32Pair > lclDecodeInt32Pair( const AttributeList& rAttribs, sal_Int32 nToken )
65 : : {
66 [ + - ]: 174 : OptValue< OUString > oValue = rAttribs.getString( nToken );
67 [ + - ]: 174 : OptValue< Int32Pair > oRetValue;
68 [ + + ]: 174 : if( oValue.has() )
69 : : {
70 : 39 : OUString aValue1, aValue2;
71 [ + - ]: 39 : ConversionHelper::separatePair( aValue1, aValue2, oValue.get(), ',' );
72 [ + - ][ + - ]: 39 : oRetValue = Int32Pair( aValue1.toInt32(), aValue2.toInt32() );
73 : : }
74 : 174 : return oRetValue;
75 : : }
76 : :
77 : : /** Returns the percentage pair from the specified VML attribute (if present).
78 : : */
79 : 12 : OptValue< DoublePair > lclDecodePercentPair( const AttributeList& rAttribs, sal_Int32 nToken )
80 : : {
81 [ + - ]: 12 : OptValue< OUString > oValue = rAttribs.getString( nToken );
82 [ + - ]: 12 : OptValue< DoublePair > oRetValue;
83 [ - + ]: 12 : if( oValue.has() )
84 : : {
85 : 0 : OUString aValue1, aValue2;
86 [ # # ]: 0 : ConversionHelper::separatePair( aValue1, aValue2, oValue.get(), ',' );
87 : : oRetValue = DoublePair(
88 [ # # ]: 0 : ConversionHelper::decodePercent( aValue1, 0.0 ),
89 [ # # ][ # # ]: 0 : ConversionHelper::decodePercent( aValue2, 0.0 ) );
[ # # ]
90 : : }
91 : 12 : return oRetValue;
92 : : }
93 : :
94 : : /** Returns the boolean value from the passed string of an attribute in the x:
95 : : namespace (VML for spreadsheets). Supported values: f, t, False, True.
96 : : @param bDefaultForEmpty Default value for the empty string.
97 : : */
98 : 3 : bool lclDecodeVmlxBool( const OUString& rValue, bool bDefaultForEmpty )
99 : : {
100 [ + - ]: 3 : if( rValue.isEmpty() ) return bDefaultForEmpty;
101 : 0 : sal_Int32 nToken = AttributeConversion::decodeToken( rValue );
102 : : // anything else than 't' or 'True' is considered to be false, as specified
103 [ # # ][ # # ]: 3 : return (nToken == XML_t) || (nToken == XML_True);
104 : : }
105 : :
106 : : } // namespace
107 : :
108 : : // ============================================================================
109 : :
110 : 3 : ShapeLayoutContext::ShapeLayoutContext( ContextHandler2Helper& rParent, Drawing& rDrawing ) :
111 : : ContextHandler2( rParent ),
112 : 3 : mrDrawing( rDrawing )
113 : : {
114 : 3 : }
115 : :
116 : :
117 : 3 : ContextHandlerRef ShapeLayoutContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
118 : : {
119 [ + - ]: 3 : switch( nElement )
120 : : {
121 : : case O_TOKEN( idmap ):
122 : : {
123 [ + - ]: 3 : OUString aBlockIds = rAttribs.getString( XML_data, OUString() );
124 : 3 : sal_Int32 nIndex = 0;
125 [ + + ]: 6 : while( nIndex >= 0 )
126 : : {
127 : 3 : OUString aToken = aBlockIds.getToken( 0, ' ', nIndex ).trim();
128 [ + - ]: 3 : if( !aToken.isEmpty() )
129 [ + - ]: 3 : mrDrawing.registerBlockId( aToken.toInt32() );
130 : 6 : }
131 : : }
132 : 3 : break;
133 : : }
134 : 3 : return 0;
135 : : }
136 : :
137 : : // ============================================================================
138 : :
139 : 6 : ClientDataContext::ClientDataContext( ContextHandler2Helper& rParent,
140 : : ClientData& rClientData, const AttributeList& rAttribs ) :
141 : : ContextHandler2( rParent ),
142 : 6 : mrClientData( rClientData )
143 : : {
144 [ + - ]: 6 : mrClientData.mnObjType = rAttribs.getToken( XML_ObjectType, XML_TOKEN_INVALID );
145 : 6 : }
146 : :
147 : 39 : ContextHandlerRef ClientDataContext::onCreateContext( sal_Int32 /*nElement*/, const AttributeList& /*rAttribs*/ )
148 : : {
149 [ + - ]: 39 : if( isRootElement() )
150 : : {
151 : 39 : maElementText = OUString();
152 : 39 : return this;
153 : : }
154 : 39 : return 0;
155 : : }
156 : :
157 : 51 : void ClientDataContext::onCharacters( const OUString& rChars )
158 : : {
159 : : /* Empty but existing elements have special meaning, e.g. 'true'. Collect
160 : : existing text and convert it in onEndElement(). */
161 : 51 : maElementText = rChars;
162 : 51 : }
163 : :
164 : 45 : void ClientDataContext::onEndElement()
165 : : {
166 [ + - - - : 45 : switch( getCurrentElement() )
- - - + +
+ + - - -
- - - - -
- - - - +
- - - -
+ ]
167 : : {
168 : 6 : case VMLX_TOKEN( Anchor ): mrClientData.maAnchor = maElementText; break;
169 : 0 : case VMLX_TOKEN( FmlaMacro ): mrClientData.maFmlaMacro = maElementText; break;
170 : 0 : case VMLX_TOKEN( FmlaPict ): mrClientData.maFmlaPict = maElementText; break;
171 : 0 : case VMLX_TOKEN( FmlaLink ): mrClientData.maFmlaLink = maElementText; break;
172 : 0 : case VMLX_TOKEN( FmlaRange ): mrClientData.maFmlaRange = maElementText; break;
173 : 0 : case VMLX_TOKEN( FmlaGroup ): mrClientData.maFmlaGroup = maElementText; break;
174 : 0 : case VMLX_TOKEN( TextHAlign ): mrClientData.mnTextHAlign = AttributeConversion::decodeToken( maElementText ); break;
175 : 3 : case VMLX_TOKEN( TextVAlign ): mrClientData.mnTextVAlign = AttributeConversion::decodeToken( maElementText ); break;
176 : 3 : case VMLX_TOKEN( Column ): mrClientData.mnCol = maElementText.toInt32(); break;
177 : 3 : case VMLX_TOKEN( Row ): mrClientData.mnRow = maElementText.toInt32(); break;
178 : 3 : case VMLX_TOKEN( Checked ): mrClientData.mnChecked = maElementText.toInt32(); break;
179 : 0 : case VMLX_TOKEN( DropStyle ): mrClientData.mnDropStyle = AttributeConversion::decodeToken( maElementText ); break;
180 : 0 : case VMLX_TOKEN( DropLines ): mrClientData.mnDropLines = maElementText.toInt32(); break;
181 : 0 : case VMLX_TOKEN( Val ): mrClientData.mnVal = maElementText.toInt32(); break;
182 : 0 : case VMLX_TOKEN( Min ): mrClientData.mnMin = maElementText.toInt32(); break;
183 : 0 : case VMLX_TOKEN( Max ): mrClientData.mnMax = maElementText.toInt32(); break;
184 : 0 : case VMLX_TOKEN( Inc ): mrClientData.mnInc = maElementText.toInt32(); break;
185 : 0 : case VMLX_TOKEN( Page ): mrClientData.mnPage = maElementText.toInt32(); break;
186 : 0 : case VMLX_TOKEN( SelType ): mrClientData.mnSelType = AttributeConversion::decodeToken( maElementText ); break;
187 : 0 : case VMLX_TOKEN( VTEdit ): mrClientData.mnVTEdit = maElementText.toInt32(); break;
188 : 0 : case VMLX_TOKEN( PrintObject ): mrClientData.mbPrintObject = lclDecodeVmlxBool( maElementText, true ); break;
189 : 0 : case VMLX_TOKEN( Visible ): mrClientData.mbVisible = lclDecodeVmlxBool( maElementText, true ); break;
190 : 0 : case VMLX_TOKEN( DDE ): mrClientData.mbDde = lclDecodeVmlxBool( maElementText, true ); break;
191 : 3 : case VMLX_TOKEN( NoThreeD ): mrClientData.mbNo3D = lclDecodeVmlxBool( maElementText, true ); break;
192 : 0 : case VMLX_TOKEN( NoThreeD2 ): mrClientData.mbNo3D2 = lclDecodeVmlxBool( maElementText, true ); break;
193 : 0 : case VMLX_TOKEN( MultiLine ): mrClientData.mbMultiLine = lclDecodeVmlxBool( maElementText, true ); break;
194 : 0 : case VMLX_TOKEN( VScroll ): mrClientData.mbVScroll = lclDecodeVmlxBool( maElementText, true ); break;
195 : 0 : case VMLX_TOKEN( SecretEdit ): mrClientData.mbSecretEdit = lclDecodeVmlxBool( maElementText, true ); break;
196 : : }
197 : 45 : }
198 : :
199 : : // ============================================================================
200 : :
201 : 87 : ShapeContextBase::ShapeContextBase( ContextHandler2Helper& rParent ) :
202 : 87 : ContextHandler2( rParent )
203 : : {
204 : 87 : }
205 : :
206 : 93 : /*static*/ ContextHandlerRef ShapeContextBase::createShapeContext( ContextHandler2Helper& rParent,
207 : : ShapeContainer& rShapes, sal_Int32 nElement, const AttributeList& rAttribs )
208 : : {
209 [ + + + + : 93 : switch( nElement )
+ - - - +
- + ]
210 : : {
211 : : case O_TOKEN( shapelayout ):
212 [ + - ]: 3 : return new ShapeLayoutContext( rParent, rShapes.getDrawing() );
213 : :
214 : : case VML_TOKEN( shapetype ):
215 [ + - ]: 30 : return new ShapeTypeContext( rParent, rShapes.createShapeType(), rAttribs );
216 : : case VML_TOKEN( group ):
217 [ + - ]: 6 : return new GroupShapeContext( rParent, rShapes.createShape< GroupShape >(), rAttribs );
218 : : case VML_TOKEN( shape ):
219 [ + - ]: 36 : return new ShapeContext( rParent, rShapes.createShape< ComplexShape >(), rAttribs );
220 : : case VML_TOKEN( rect ):
221 [ + - ]: 12 : return new RectangleShapeContext( rParent, rAttribs, rShapes.createShape< RectangleShape >() );
222 : : case VML_TOKEN( roundrect ):
223 [ # # ]: 0 : return new ShapeContext( rParent, rShapes.createShape< RectangleShape >(), rAttribs );
224 : : case VML_TOKEN( oval ):
225 [ # # ]: 0 : return new ShapeContext( rParent, rShapes.createShape< EllipseShape >(), rAttribs );
226 : : case VML_TOKEN( polyline ):
227 [ # # ]: 0 : return new ShapeContext( rParent, rShapes.createShape< PolyLineShape >(), rAttribs );
228 : : case VML_TOKEN( line ):
229 [ + - ]: 3 : return new ShapeContext( rParent, rShapes.createShape< LineShape >(), rAttribs );
230 : :
231 : : // TODO:
232 : : case VML_TOKEN( arc ):
233 : : case VML_TOKEN( curve ):
234 : : case VML_TOKEN( diagram ):
235 : : case VML_TOKEN( image ):
236 [ # # ]: 0 : return new ShapeContext( rParent, rShapes.createShape< ComplexShape >(), rAttribs );
237 : : }
238 : 93 : return 0;
239 : : }
240 : :
241 : : // ============================================================================
242 : :
243 : 87 : ShapeTypeContext::ShapeTypeContext( ContextHandler2Helper& rParent, ShapeType& rShapeType, const AttributeList& rAttribs ) :
244 : : ShapeContextBase( rParent ),
245 : 87 : mrTypeModel( rShapeType.getTypeModel() )
246 : : {
247 : : // shape identifier and shape name
248 [ + - ]: 87 : bool bHasOspid = rAttribs.hasAttribute( O_TOKEN( spid ) );
249 [ + + ][ + - ]: 87 : mrTypeModel.maShapeId = rAttribs.getXString( bHasOspid ? O_TOKEN( spid ) : XML_id, OUString() );
250 : : OSL_ENSURE( !mrTypeModel.maShapeId.isEmpty(), "ShapeTypeContext::ShapeTypeContext - missing shape identifier" );
251 : : // if the o:spid attribute exists, the id attribute contains the user-defined shape name
252 [ + + ]: 87 : if( bHasOspid )
253 [ + - ]: 6 : mrTypeModel.maShapeName = rAttribs.getXString( XML_id, OUString() );
254 : : // builtin shape type identifier
255 [ + - ]: 87 : mrTypeModel.moShapeType = rAttribs.getInteger( O_TOKEN( spt ) );
256 : :
257 : : // coordinate system position/size, CSS style
258 [ + - ]: 87 : mrTypeModel.moCoordPos = lclDecodeInt32Pair( rAttribs, XML_coordorigin );
259 [ + - ]: 87 : mrTypeModel.moCoordSize = lclDecodeInt32Pair( rAttribs, XML_coordsize );
260 [ + - ][ + - ]: 87 : setStyle( rAttribs.getString( XML_style, OUString() ) );
261 [ - + ][ + - ]: 87 : if( lclDecodeBool( rAttribs, O_TOKEN( hr )).get( false ))
262 : : { // MSO's handling of o:hr width is nowhere near what the spec says:
263 : : // - o:hrpct is not in % but in 0.1%
264 : : // - if o:hrpct is not given, 100% width is assumed
265 : : // - given width is used only if explicit o:hrpct="0" is given
266 [ # # ]: 0 : OUString hrpct = rAttribs.getString( O_TOKEN( hrpct ), "1000" );
267 [ # # ]: 0 : if( hrpct != "0" )
268 : 0 : mrTypeModel.maWidth = OUString::valueOf( hrpct.toInt32() / 10 ) + "%";
269 : : }
270 : :
271 : : // stroke settings (may be overridden by v:stroke element later)
272 [ + - ]: 87 : mrTypeModel.maStrokeModel.moStroked = lclDecodeBool( rAttribs, XML_stroked );
273 [ + - ]: 87 : mrTypeModel.maStrokeModel.moColor = rAttribs.getString( XML_strokecolor );
274 [ + - ]: 87 : mrTypeModel.maStrokeModel.moWeight = rAttribs.getString( XML_strokeweight );
275 : :
276 : : // fill settings (may be overridden by v:fill element later)
277 [ + - ]: 87 : mrTypeModel.maFillModel.moFilled = lclDecodeBool( rAttribs, XML_filled );
278 [ + - ]: 87 : mrTypeModel.maFillModel.moColor = rAttribs.getString( XML_fillcolor );
279 : 87 : }
280 : :
281 : 117 : ContextHandlerRef ShapeTypeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
282 : : {
283 [ + - ][ + + : 117 : if( isRootElement() ) switch( nElement )
+ + + ]
284 : : {
285 : : case VML_TOKEN( stroke ):
286 [ + - ]: 33 : mrTypeModel.maStrokeModel.moStroked.assignIfUsed( lclDecodeBool( rAttribs, XML_on ) );
287 : 33 : mrTypeModel.maStrokeModel.maStartArrow.moArrowType = rAttribs.getToken( XML_startarrow );
288 : 33 : mrTypeModel.maStrokeModel.maStartArrow.moArrowWidth = rAttribs.getToken( XML_startarrowwidth );
289 : 33 : mrTypeModel.maStrokeModel.maStartArrow.moArrowLength = rAttribs.getToken( XML_startarrowlength );
290 : 33 : mrTypeModel.maStrokeModel.maEndArrow.moArrowType = rAttribs.getToken( XML_endarrow );
291 : 33 : mrTypeModel.maStrokeModel.maEndArrow.moArrowWidth = rAttribs.getToken( XML_endarrowwidth );
292 : 33 : mrTypeModel.maStrokeModel.maEndArrow.moArrowLength = rAttribs.getToken( XML_endarrowlength );
293 [ + - ]: 33 : mrTypeModel.maStrokeModel.moColor.assignIfUsed( rAttribs.getString( XML_color ) );
294 : 33 : mrTypeModel.maStrokeModel.moOpacity = lclDecodePercent( rAttribs, XML_opacity, 1.0 );
295 [ + - ]: 33 : mrTypeModel.maStrokeModel.moWeight.assignIfUsed( rAttribs.getString( XML_weight ) );
296 : 33 : mrTypeModel.maStrokeModel.moDashStyle = rAttribs.getString( XML_dashstyle );
297 : 33 : mrTypeModel.maStrokeModel.moLineStyle = rAttribs.getToken( XML_linestyle );
298 : 33 : mrTypeModel.maStrokeModel.moEndCap = rAttribs.getToken( XML_endcap );
299 : 33 : mrTypeModel.maStrokeModel.moJoinStyle = rAttribs.getToken( XML_joinstyle );
300 : 33 : break;
301 : : case VML_TOKEN( fill ):
302 [ + - ]: 6 : mrTypeModel.maFillModel.moFilled.assignIfUsed( lclDecodeBool( rAttribs, XML_on ) );
303 [ + - ]: 6 : mrTypeModel.maFillModel.moColor.assignIfUsed( rAttribs.getString( XML_color ) );
304 : 6 : mrTypeModel.maFillModel.moOpacity = lclDecodePercent( rAttribs, XML_opacity, 1.0 );
305 : 6 : mrTypeModel.maFillModel.moColor2 = rAttribs.getString( XML_color2 );
306 : 6 : mrTypeModel.maFillModel.moOpacity2 = lclDecodePercent( rAttribs, XML_opacity2, 1.0 );
307 : 6 : mrTypeModel.maFillModel.moType = rAttribs.getToken( XML_type );
308 : 6 : mrTypeModel.maFillModel.moAngle = rAttribs.getInteger( XML_angle );
309 : 6 : mrTypeModel.maFillModel.moFocus = lclDecodePercent( rAttribs, XML_focus, 0.0 );
310 : 6 : mrTypeModel.maFillModel.moFocusPos = lclDecodePercentPair( rAttribs, XML_focusposition );
311 : 6 : mrTypeModel.maFillModel.moFocusSize = lclDecodePercentPair( rAttribs, XML_focussize );
312 : 6 : mrTypeModel.maFillModel.moBitmapPath = decodeFragmentPath( rAttribs, O_TOKEN( relid ) );
313 : 6 : mrTypeModel.maFillModel.moRotate = lclDecodeBool( rAttribs, XML_rotate );
314 : 6 : break;
315 : : case VML_TOKEN( imagedata ):
316 : : {
317 : : // shapes in docx use r:id for the relationship id
318 : : // in xlsx it they use o:relid
319 : 12 : bool bHasORelId = rAttribs.hasAttribute( O_TOKEN( relid ) );
320 [ - + ]: 12 : mrTypeModel.moGraphicPath = decodeFragmentPath( rAttribs, bHasORelId ? O_TOKEN( relid ) : R_TOKEN( id ) );
321 : 12 : mrTypeModel.moGraphicTitle = rAttribs.getString( O_TOKEN( title ) );
322 : : }
323 : 12 : break;
324 : : case NMSP_vmlWord | XML_wrap:
325 : 12 : mrTypeModel.moWrapAnchorX = rAttribs.getString(XML_anchorx);
326 : 12 : mrTypeModel.moWrapAnchorY = rAttribs.getString(XML_anchory);
327 : 117 : break;
328 : : }
329 : 117 : return 0;
330 : : }
331 : :
332 : 18 : OptValue< OUString > ShapeTypeContext::decodeFragmentPath( const AttributeList& rAttribs, sal_Int32 nToken ) const
333 : : {
334 : 18 : OptValue< OUString > oFragmentPath;
335 [ + - ]: 18 : OptValue< OUString > oRelId = rAttribs.getString( nToken );
336 [ + + ]: 18 : if( oRelId.has() )
337 [ + - ][ + - ]: 12 : oFragmentPath = getFragmentPathFromRelId( oRelId.get() );
338 : 18 : return oFragmentPath;
339 : : }
340 : :
341 : 87 : void ShapeTypeContext::setStyle( const OUString& rStyle )
342 : : {
343 : 87 : sal_Int32 nIndex = 0;
344 [ + + ]: 537 : while( nIndex >= 0 )
345 : : {
346 : 450 : OUString aName, aValue;
347 [ + + ][ + - ]: 450 : if( ConversionHelper::separatePair( aName, aValue, rStyle.getToken( 0, ';', nIndex ), ':' ) )
348 : : {
349 [ + + ]: 420 : if( aName == "position" ) mrTypeModel.maPosition = aValue;
350 [ + + ]: 372 : else if( aName == "left" ) mrTypeModel.maLeft = aValue;
351 [ + + ]: 357 : else if( aName == "top" ) mrTypeModel.maTop = aValue;
352 [ + + ]: 345 : else if( aName == "width" ) mrTypeModel.maWidth = aValue;
353 [ + + ]: 291 : else if( aName == "height" ) mrTypeModel.maHeight = aValue;
354 [ + + ]: 237 : else if( aName == "margin-left" ) mrTypeModel.maMarginLeft = aValue;
355 [ + + ]: 207 : else if( aName == "margin-top" ) mrTypeModel.maMarginTop = aValue;
356 [ + + ]: 177 : else if( aName == "mso-position-vertical-relative" ) mrTypeModel.maPositionVerticalRelative = aValue;
357 [ + + ]: 159 : else if( aName == "mso-position-horizontal" ) mrTypeModel.maPositionHorizontal = aValue;
358 [ - + ]: 147 : else if( aName == "mso-fit-shape-to-text" ) mrTypeModel.mbAutoHeight = sal_True;
359 [ + + ]: 147 : else if( aName == "rotation" ) mrTypeModel.maRotation = aValue;
360 [ + + ]: 144 : else if( aName == "flip" ) mrTypeModel.maFlip = aValue;
361 [ + + ]: 141 : else if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "visibility" ) ) )
362 : 9 : mrTypeModel.mbVisible = !aValue.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("hidden") );
363 [ + + ]: 132 : else if( aName == "mso-wrap-style" ) mrTypeModel.maWrapStyle = aValue;
364 : : }
365 : 450 : }
366 : 87 : }
367 : :
368 : : // ============================================================================
369 : :
370 : 57 : ShapeContext::ShapeContext( ContextHandler2Helper& rParent, ShapeBase& rShape, const AttributeList& rAttribs ) :
371 : : ShapeTypeContext( rParent, rShape, rAttribs ),
372 : : mrShape( rShape ),
373 : 57 : mrShapeModel( rShape.getShapeModel() )
374 : : {
375 : : // collect shape specific attributes
376 [ + - ]: 57 : mrShapeModel.maType = rAttribs.getXString( XML_type, OUString() );
377 : : // polyline path
378 [ + - ][ + - ]: 57 : setPoints( rAttribs.getString( XML_points, OUString() ) );
379 : : // line start and end positions
380 [ + - ]: 57 : setFrom(rAttribs.getString(XML_from, OUString()));
381 [ + - ]: 57 : setTo(rAttribs.getString(XML_to, OUString()));
382 : 57 : }
383 : :
384 : 84 : ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
385 : : {
386 : : // Excel specific shape client data
387 [ + - ]: 84 : if( isRootElement() ) switch( nElement )
[ + + - + ]
388 : : {
389 : : case VML_TOKEN( textbox ):
390 : : // Custom shape in Writer with a textbox are transformed into a frame
391 : 27 : dynamic_cast<SimpleShape&>( mrShape ).setService(
392 [ + - ]: 54 : "com.sun.star.text.TextFrame");
393 [ + - ]: 27 : return new TextBoxContext( *this, mrShapeModel.createTextBox(), rAttribs );
394 : : case VMLX_TOKEN( ClientData ):
395 [ + - ]: 6 : return new ClientDataContext( *this, mrShapeModel.createClientData(), rAttribs );
396 : : case VMLPPT_TOKEN( textdata ):
397 : : // Force RectangleShape, this is ugly :(
398 : : // and is there because of the lines above which change it to TextFrame
399 : 0 : dynamic_cast< SimpleShape& >( mrShape ).setService(
400 [ # # ]: 0 : "com.sun.star.drawing.RectangleShape");
401 [ # # ][ # # ]: 0 : mrShapeModel.maLegacyDiagramPath = getFragmentPathFromRelId(rAttribs.getString(XML_id, OUString()));
402 : 51 : break;
403 : : }
404 : : // handle remaining stuff in base class
405 : 84 : return ShapeTypeContext::onCreateContext( nElement, rAttribs );
406 : : }
407 : :
408 : 57 : void ShapeContext::setPoints( const OUString& rPoints )
409 : : {
410 : 57 : mrShapeModel.maPoints.clear();
411 : 57 : sal_Int32 nIndex = 0;
412 [ + + ]: 114 : while( nIndex >= 0 )
413 : : {
414 : 57 : sal_Int32 nX = rPoints.getToken( 0, ',', nIndex ).toInt32();
415 : 57 : sal_Int32 nY = rPoints.getToken( 0, ',', nIndex ).toInt32();
416 [ + - ]: 57 : mrShapeModel.maPoints.push_back( Point( nX, nY ) );
417 : : }
418 : 57 : }
419 : :
420 : 57 : void ShapeContext::setFrom( const OUString& rPoints )
421 : : {
422 [ + + ]: 57 : if (!rPoints.isEmpty())
423 : 3 : mrShapeModel.maFrom = rPoints;
424 : 57 : }
425 : :
426 : 57 : void ShapeContext::setTo( const OUString& rPoints )
427 : : {
428 [ + + ]: 57 : if (!rPoints.isEmpty())
429 : 3 : mrShapeModel.maTo = rPoints;
430 : 57 : }
431 : :
432 : : // ============================================================================
433 : :
434 : 6 : GroupShapeContext::GroupShapeContext( ContextHandler2Helper& rParent, GroupShape& rShape, const AttributeList& rAttribs ) :
435 : : ShapeContext( rParent, rShape, rAttribs ),
436 : 6 : mrShapes( rShape.getChildren() )
437 : : {
438 : 6 : }
439 : :
440 : 15 : ContextHandlerRef GroupShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
441 : : {
442 : : // try to create a context of an embedded shape
443 [ + - ]: 15 : ContextHandlerRef xContext = createShapeContext( *this, mrShapes, nElement, rAttribs );
444 : : // handle remaining stuff of this shape in base class
445 [ + + ][ + - ]: 15 : return xContext.get() ? xContext : ShapeContext::onCreateContext( nElement, rAttribs );
446 : : }
447 : :
448 : : // ============================================================================
449 : :
450 : 12 : RectangleShapeContext::RectangleShapeContext( ContextHandler2Helper& rParent, const AttributeList& rAttribs, RectangleShape& rShape ) :
451 : 12 : ShapeContext( rParent, rShape, rAttribs )
452 : : {
453 : 12 : }
454 : :
455 : 12 : ContextHandlerRef RectangleShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
456 : : {
457 : : // The parent class's context is fine
458 : 12 : return ShapeContext::onCreateContext( nElement, rAttribs );
459 : : }
460 : : // ============================================================================
461 : :
462 : : } // namespace vml
463 [ + - ][ + - ]: 285 : } // namespace oox
464 : :
465 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|