bump product version to 4.2.0.1
[LibreOffice.git] / oox / source / vml / vmlshapecontext.cxx
blobbe12b954224eb42ef386df18c949d4938a281949
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/vmlshapecontext.hxx"
22 #include "oox/core/xmlfilterbase.hxx"
23 #include "oox/vml/vmldrawing.hxx"
24 #include "oox/vml/vmlshape.hxx"
25 #include "oox/vml/vmlshapecontainer.hxx"
26 #include "oox/vml/vmltextboxcontext.hxx"
28 namespace oox {
29 namespace vml {
31 // ============================================================================
33 using namespace ::com::sun::star;
35 using ::oox::core::ContextHandler2;
36 using ::oox::core::ContextHandler2Helper;
37 using ::oox::core::ContextHandlerRef;
39 // ============================================================================
41 namespace {
43 /** Returns the boolean value from the specified VML attribute (if present).
45 OptValue< bool > lclDecodeBool( const AttributeList& rAttribs, sal_Int32 nToken )
47 OptValue< OUString > oValue = rAttribs.getString( nToken );
48 if( oValue.has() ) return OptValue< bool >( ConversionHelper::decodeBool( oValue.get() ) );
49 return OptValue< bool >();
52 /** Returns the percentage value from the specified VML attribute (if present).
53 The value will be normalized (1.0 is returned for 100%).
55 OptValue< double > lclDecodePercent( const AttributeList& rAttribs, sal_Int32 nToken, double fDefValue )
57 OptValue< OUString > oValue = rAttribs.getString( nToken );
58 if( oValue.has() ) return OptValue< double >( ConversionHelper::decodePercent( oValue.get(), fDefValue ) );
59 return OptValue< double >();
62 /** #119750# Special method for opacity; it *should* be a percentage value, but there are cases
63 where a value relative to 0xffff (65536) is used, ending with an 'f'
65 OptValue< double > lclDecodeOpacity( const AttributeList& rAttribs, sal_Int32 nToken, double fDefValue )
67 OptValue< OUString > oValue = rAttribs.getString( nToken );
68 double fRetval(fDefValue);
70 if( oValue.has() )
72 const OUString aString(oValue.get());
73 const sal_Int32 nLength(aString.getLength());
75 if(nLength > 0)
77 if(aString.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM("f")))
79 fRetval = std::max(0.0, std::min(1.0, aString.toDouble() / 65536.0));
81 else
83 fRetval = ConversionHelper::decodePercent( aString, fDefValue );
88 return OptValue< double >(fRetval);
91 /** Returns the integer value pair from the specified VML attribute (if present).
93 OptValue< Int32Pair > lclDecodeInt32Pair( const AttributeList& rAttribs, sal_Int32 nToken )
95 OptValue< OUString > oValue = rAttribs.getString( nToken );
96 OptValue< Int32Pair > oRetValue;
97 if( oValue.has() )
99 OUString aValue1, aValue2;
100 ConversionHelper::separatePair( aValue1, aValue2, oValue.get(), ',' );
101 oRetValue = Int32Pair( aValue1.toInt32(), aValue2.toInt32() );
103 return oRetValue;
106 /** Returns the percentage pair from the specified VML attribute (if present).
108 OptValue< DoublePair > lclDecodePercentPair( const AttributeList& rAttribs, sal_Int32 nToken )
110 OptValue< OUString > oValue = rAttribs.getString( nToken );
111 OptValue< DoublePair > oRetValue;
112 if( oValue.has() )
114 OUString aValue1, aValue2;
115 ConversionHelper::separatePair( aValue1, aValue2, oValue.get(), ',' );
116 oRetValue = DoublePair(
117 ConversionHelper::decodePercent( aValue1, 0.0 ),
118 ConversionHelper::decodePercent( aValue2, 0.0 ) );
120 return oRetValue;
123 /** Returns the boolean value from the passed string of an attribute in the x:
124 namespace (VML for spreadsheets). Supported values: f, t, False, True.
125 @param bDefaultForEmpty Default value for the empty string.
127 bool lclDecodeVmlxBool( const OUString& rValue, bool bDefaultForEmpty )
129 if( rValue.isEmpty() ) return bDefaultForEmpty;
130 sal_Int32 nToken = AttributeConversion::decodeToken( rValue );
131 // anything else than 't' or 'True' is considered to be false, as specified
132 return (nToken == XML_t) || (nToken == XML_True);
135 } // namespace
137 // ============================================================================
139 ShapeLayoutContext::ShapeLayoutContext( ContextHandler2Helper& rParent, Drawing& rDrawing ) :
140 ContextHandler2( rParent ),
141 mrDrawing( rDrawing )
146 ContextHandlerRef ShapeLayoutContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
148 switch( nElement )
150 case O_TOKEN( idmap ):
152 OUString aBlockIds = rAttribs.getString( XML_data, OUString() );
153 sal_Int32 nIndex = 0;
154 while( nIndex >= 0 )
156 OUString aToken = aBlockIds.getToken( 0, ' ', nIndex ).trim();
157 if( !aToken.isEmpty() )
158 mrDrawing.registerBlockId( aToken.toInt32() );
161 break;
163 return 0;
166 // ============================================================================
168 ClientDataContext::ClientDataContext( ContextHandler2Helper& rParent,
169 ClientData& rClientData, const AttributeList& rAttribs ) :
170 ContextHandler2( rParent ),
171 mrClientData( rClientData )
173 mrClientData.mnObjType = rAttribs.getToken( XML_ObjectType, XML_TOKEN_INVALID );
176 ContextHandlerRef ClientDataContext::onCreateContext( sal_Int32 /*nElement*/, const AttributeList& /*rAttribs*/ )
178 if( isRootElement() )
180 maElementText = OUString();
181 return this;
183 return 0;
186 void ClientDataContext::onCharacters( const OUString& rChars )
188 /* Empty but existing elements have special meaning, e.g. 'true'. Collect
189 existing text and convert it in onEndElement(). */
190 maElementText = rChars;
193 void ClientDataContext::onEndElement()
195 switch( getCurrentElement() )
197 case VMLX_TOKEN( Anchor ): mrClientData.maAnchor = maElementText; break;
198 case VMLX_TOKEN( FmlaMacro ): mrClientData.maFmlaMacro = maElementText; break;
199 case VMLX_TOKEN( FmlaPict ): mrClientData.maFmlaPict = maElementText; break;
200 case VMLX_TOKEN( FmlaLink ): mrClientData.maFmlaLink = maElementText; break;
201 case VMLX_TOKEN( FmlaRange ): mrClientData.maFmlaRange = maElementText; break;
202 case VMLX_TOKEN( FmlaGroup ): mrClientData.maFmlaGroup = maElementText; break;
203 case VMLX_TOKEN( TextHAlign ): mrClientData.mnTextHAlign = AttributeConversion::decodeToken( maElementText ); break;
204 case VMLX_TOKEN( TextVAlign ): mrClientData.mnTextVAlign = AttributeConversion::decodeToken( maElementText ); break;
205 case VMLX_TOKEN( Column ): mrClientData.mnCol = maElementText.toInt32(); break;
206 case VMLX_TOKEN( Row ): mrClientData.mnRow = maElementText.toInt32(); break;
207 case VMLX_TOKEN( Checked ): mrClientData.mnChecked = maElementText.toInt32(); break;
208 case VMLX_TOKEN( DropStyle ): mrClientData.mnDropStyle = AttributeConversion::decodeToken( maElementText ); break;
209 case VMLX_TOKEN( DropLines ): mrClientData.mnDropLines = maElementText.toInt32(); break;
210 case VMLX_TOKEN( Val ): mrClientData.mnVal = maElementText.toInt32(); break;
211 case VMLX_TOKEN( Min ): mrClientData.mnMin = maElementText.toInt32(); break;
212 case VMLX_TOKEN( Max ): mrClientData.mnMax = maElementText.toInt32(); break;
213 case VMLX_TOKEN( Inc ): mrClientData.mnInc = maElementText.toInt32(); break;
214 case VMLX_TOKEN( Page ): mrClientData.mnPage = maElementText.toInt32(); break;
215 case VMLX_TOKEN( SelType ): mrClientData.mnSelType = AttributeConversion::decodeToken( maElementText ); break;
216 case VMLX_TOKEN( VTEdit ): mrClientData.mnVTEdit = maElementText.toInt32(); break;
217 case VMLX_TOKEN( PrintObject ): mrClientData.mbPrintObject = lclDecodeVmlxBool( maElementText, true ); break;
218 case VMLX_TOKEN( Visible ): mrClientData.mbVisible = lclDecodeVmlxBool( maElementText, true ); break;
219 case VMLX_TOKEN( DDE ): mrClientData.mbDde = lclDecodeVmlxBool( maElementText, true ); break;
220 case VMLX_TOKEN( NoThreeD ): mrClientData.mbNo3D = lclDecodeVmlxBool( maElementText, true ); break;
221 case VMLX_TOKEN( NoThreeD2 ): mrClientData.mbNo3D2 = lclDecodeVmlxBool( maElementText, true ); break;
222 case VMLX_TOKEN( MultiLine ): mrClientData.mbMultiLine = lclDecodeVmlxBool( maElementText, true ); break;
223 case VMLX_TOKEN( VScroll ): mrClientData.mbVScroll = lclDecodeVmlxBool( maElementText, true ); break;
224 case VMLX_TOKEN( SecretEdit ): mrClientData.mbSecretEdit = lclDecodeVmlxBool( maElementText, true ); break;
228 // ============================================================================
230 ShapeContextBase::ShapeContextBase( ContextHandler2Helper& rParent ) :
231 ContextHandler2( rParent )
235 ContextHandlerRef ShapeContextBase::createShapeContext( ContextHandler2Helper& rParent,
236 ShapeContainer& rShapes, sal_Int32 nElement, const AttributeList& rAttribs )
238 switch( nElement )
240 case O_TOKEN( shapelayout ):
241 return new ShapeLayoutContext( rParent, rShapes.getDrawing() );
243 case VML_TOKEN( shapetype ):
244 return new ShapeTypeContext( rParent, rShapes.createShapeType(), rAttribs );
245 case VML_TOKEN( group ):
246 return new GroupShapeContext( rParent, rShapes.createShape< GroupShape >(), rAttribs );
247 case VML_TOKEN( shape ):
248 if (rAttribs.hasAttribute(XML_path))
249 return new ShapeContext( rParent, rShapes.createShape< BezierShape >(), rAttribs );
250 else
251 return new ShapeContext( rParent, rShapes.createShape< ComplexShape >(), rAttribs );
252 case VML_TOKEN( rect ):
253 return new RectangleShapeContext( rParent, rAttribs, rShapes.createShape< RectangleShape >() );
254 case VML_TOKEN( roundrect ):
255 return new ShapeContext( rParent, rShapes.createShape< RectangleShape >(), rAttribs );
256 case VML_TOKEN( oval ):
257 return new ShapeContext( rParent, rShapes.createShape< EllipseShape >(), rAttribs );
258 case VML_TOKEN( polyline ):
259 return new ShapeContext( rParent, rShapes.createShape< PolyLineShape >(), rAttribs );
260 case VML_TOKEN( line ):
261 return new ShapeContext( rParent, rShapes.createShape< LineShape >(), rAttribs );
262 case VML_TOKEN( curve ):
263 return new ShapeContext( rParent, rShapes.createShape< BezierShape >(), rAttribs );
265 // TODO:
266 case VML_TOKEN( arc ):
267 case VML_TOKEN( diagram ):
268 case VML_TOKEN( image ):
269 return new ShapeContext( rParent, rShapes.createShape< ComplexShape >(), rAttribs );
271 return 0;
274 // ============================================================================
276 ShapeTypeContext::ShapeTypeContext( ContextHandler2Helper& rParent, ShapeType& rShapeType, const AttributeList& rAttribs ) :
277 ShapeContextBase( rParent ),
278 mrTypeModel( rShapeType.getTypeModel() )
280 // shape identifier and shape name
281 bool bHasOspid = rAttribs.hasAttribute( O_TOKEN( spid ) );
282 mrTypeModel.maShapeId = rAttribs.getXString( bHasOspid ? O_TOKEN( spid ) : XML_id, OUString() );
283 OSL_ENSURE( !mrTypeModel.maShapeId.isEmpty(), "ShapeTypeContext::ShapeTypeContext - missing shape identifier" );
284 // if the o:spid attribute exists, the id attribute contains the user-defined shape name
285 if( bHasOspid )
286 mrTypeModel.maShapeName = rAttribs.getXString( XML_id, OUString() );
287 // builtin shape type identifier
288 mrTypeModel.moShapeType = rAttribs.getInteger( O_TOKEN( spt ) );
290 // coordinate system position/size, CSS style
291 mrTypeModel.moCoordPos = lclDecodeInt32Pair( rAttribs, XML_coordorigin );
292 mrTypeModel.moCoordSize = lclDecodeInt32Pair( rAttribs, XML_coordsize );
293 setStyle( rAttribs.getString( XML_style, OUString() ) );
294 if( lclDecodeBool( rAttribs, O_TOKEN( hr )).get( false ))
295 { // MSO's handling of o:hr width is nowhere near what the spec says:
296 // - o:hrpct is not in % but in 0.1%
297 // - if o:hrpct is not given, 100% width is assumed
298 // - given width is used only if explicit o:hrpct="0" is given
299 OUString hrpct = rAttribs.getString( O_TOKEN( hrpct ), "1000" );
300 if( hrpct != "0" )
301 mrTypeModel.maWidth = OUString::number( hrpct.toInt32() / 10 ) + "%";
304 // stroke settings (may be overridden by v:stroke element later)
305 mrTypeModel.maStrokeModel.moStroked = lclDecodeBool( rAttribs, XML_stroked );
306 mrTypeModel.maStrokeModel.moColor = rAttribs.getString( XML_strokecolor );
307 mrTypeModel.maStrokeModel.moWeight = rAttribs.getString( XML_strokeweight );
309 // fill settings (may be overridden by v:fill element later)
310 mrTypeModel.maFillModel.moFilled = lclDecodeBool( rAttribs, XML_filled );
311 mrTypeModel.maFillModel.moColor = rAttribs.getString( XML_fillcolor );
313 // For roundrect we may have a arcsize attribute to read
314 mrTypeModel.maArcsize = rAttribs.getString( XML_arcsize,OUString( ) );
317 ContextHandlerRef ShapeTypeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
319 if( isRootElement() ) switch( nElement )
321 case VML_TOKEN( stroke ):
322 mrTypeModel.maStrokeModel.moStroked.assignIfUsed( lclDecodeBool( rAttribs, XML_on ) );
323 mrTypeModel.maStrokeModel.maStartArrow.moArrowType = rAttribs.getToken( XML_startarrow );
324 mrTypeModel.maStrokeModel.maStartArrow.moArrowWidth = rAttribs.getToken( XML_startarrowwidth );
325 mrTypeModel.maStrokeModel.maStartArrow.moArrowLength = rAttribs.getToken( XML_startarrowlength );
326 mrTypeModel.maStrokeModel.maEndArrow.moArrowType = rAttribs.getToken( XML_endarrow );
327 mrTypeModel.maStrokeModel.maEndArrow.moArrowWidth = rAttribs.getToken( XML_endarrowwidth );
328 mrTypeModel.maStrokeModel.maEndArrow.moArrowLength = rAttribs.getToken( XML_endarrowlength );
329 mrTypeModel.maStrokeModel.moColor.assignIfUsed( rAttribs.getString( XML_color ) );
330 mrTypeModel.maStrokeModel.moOpacity = lclDecodeOpacity( rAttribs, XML_opacity, 1.0 );
331 mrTypeModel.maStrokeModel.moWeight.assignIfUsed( rAttribs.getString( XML_weight ) );
332 mrTypeModel.maStrokeModel.moDashStyle = rAttribs.getString( XML_dashstyle );
333 mrTypeModel.maStrokeModel.moLineStyle = rAttribs.getToken( XML_linestyle );
334 mrTypeModel.maStrokeModel.moEndCap = rAttribs.getToken( XML_endcap );
335 mrTypeModel.maStrokeModel.moJoinStyle = rAttribs.getToken( XML_joinstyle );
336 break;
337 case VML_TOKEN( fill ):
338 mrTypeModel.maFillModel.moFilled.assignIfUsed( lclDecodeBool( rAttribs, XML_on ) );
339 mrTypeModel.maFillModel.moColor.assignIfUsed( rAttribs.getString( XML_color ) );
340 mrTypeModel.maFillModel.moOpacity = lclDecodeOpacity( rAttribs, XML_opacity, 1.0 );
341 mrTypeModel.maFillModel.moColor2 = rAttribs.getString( XML_color2 );
342 mrTypeModel.maFillModel.moOpacity2 = lclDecodeOpacity( rAttribs, XML_opacity2, 1.0 );
343 mrTypeModel.maFillModel.moType = rAttribs.getToken( XML_type );
344 mrTypeModel.maFillModel.moAngle = rAttribs.getInteger( XML_angle );
345 mrTypeModel.maFillModel.moFocus = lclDecodePercent( rAttribs, XML_focus, 0.0 );
346 mrTypeModel.maFillModel.moFocusPos = lclDecodePercentPair( rAttribs, XML_focusposition );
347 mrTypeModel.maFillModel.moFocusSize = lclDecodePercentPair( rAttribs, XML_focussize );
348 mrTypeModel.maFillModel.moBitmapPath = decodeFragmentPath( rAttribs, O_TOKEN( relid ) );
349 mrTypeModel.maFillModel.moRotate = lclDecodeBool( rAttribs, XML_rotate );
350 break;
351 case VML_TOKEN( imagedata ):
353 // shapes in docx use r:id for the relationship id
354 // in xlsx it they use o:relid
355 bool bHasORelId = rAttribs.hasAttribute( O_TOKEN( relid ) );
356 mrTypeModel.moGraphicPath = decodeFragmentPath( rAttribs, bHasORelId ? O_TOKEN( relid ) : R_TOKEN( id ) );
357 mrTypeModel.moGraphicTitle = rAttribs.getString( O_TOKEN( title ) );
359 break;
360 case NMSP_vmlWord | XML_wrap:
361 mrTypeModel.moWrapAnchorX = rAttribs.getString(XML_anchorx);
362 mrTypeModel.moWrapAnchorY = rAttribs.getString(XML_anchory);
363 mrTypeModel.moWrapType = rAttribs.getString(XML_type);
364 mrTypeModel.moWrapSide = rAttribs.getString(XML_side);
365 break;
366 case VML_TOKEN( shadow ):
368 mrTypeModel.maShadowModel.mbHasShadow = true;
369 mrTypeModel.maShadowModel.moShadowOn.assignIfUsed(lclDecodeBool(rAttribs, XML_on));
370 mrTypeModel.maShadowModel.moColor.assignIfUsed(rAttribs.getString(XML_color));
371 mrTypeModel.maShadowModel.moOffset.assignIfUsed(rAttribs.getString(XML_offset));
372 mrTypeModel.maShadowModel.moOpacity = lclDecodePercent(rAttribs, XML_opacity, 1.0);
374 break;
375 case VML_TOKEN( textpath ):
376 mrTypeModel.maTextpathModel.moString.assignIfUsed(rAttribs.getString(XML_string));
377 break;
379 return 0;
382 OptValue< OUString > ShapeTypeContext::decodeFragmentPath( const AttributeList& rAttribs, sal_Int32 nToken ) const
384 OptValue< OUString > oFragmentPath;
385 OptValue< OUString > oRelId = rAttribs.getString( nToken );
386 if( oRelId.has() )
387 oFragmentPath = getFragmentPathFromRelId( oRelId.get() );
388 return oFragmentPath;
391 void ShapeTypeContext::setStyle( const OUString& rStyle )
393 sal_Int32 nIndex = 0;
394 while( nIndex >= 0 )
396 OUString aName, aValue;
397 if( ConversionHelper::separatePair( aName, aValue, rStyle.getToken( 0, ';', nIndex ), ':' ) )
399 if( aName == "position" ) mrTypeModel.maPosition = aValue;
400 else if( aName == "left" ) mrTypeModel.maLeft = aValue;
401 else if( aName == "top" ) mrTypeModel.maTop = aValue;
402 else if( aName == "width" ) mrTypeModel.maWidth = aValue;
403 else if( aName == "height" ) mrTypeModel.maHeight = aValue;
404 else if( aName == "margin-left" ) mrTypeModel.maMarginLeft = aValue;
405 else if( aName == "margin-top" ) mrTypeModel.maMarginTop = aValue;
406 else if( aName == "mso-position-vertical-relative" ) mrTypeModel.maPositionVerticalRelative = aValue;
407 else if( aName == "mso-position-horizontal-relative" ) mrTypeModel.maPositionHorizontalRelative = aValue;
408 else if( aName == "mso-position-horizontal" ) mrTypeModel.maPositionHorizontal = aValue;
409 else if( aName == "mso-position-vertical" ) mrTypeModel.maPositionVertical = aValue;
410 else if( aName == "mso-width-percent" ) mrTypeModel.maWidthPercent = aValue;
411 else if( aName == "mso-width-relative" ) mrTypeModel.maWidthRelative = aValue;
412 else if( aName == "mso-height-percent" ) mrTypeModel.maHeightPercent = aValue;
413 else if( aName == "mso-height-relative" ) mrTypeModel.maHeightRelative = aValue;
414 else if( aName == "mso-fit-shape-to-text" ) mrTypeModel.mbAutoHeight = sal_True;
415 else if( aName == "rotation" ) mrTypeModel.maRotation = aValue;
416 else if( aName == "flip" ) mrTypeModel.maFlip = aValue;
417 else if( aName.equalsAscii( "visibility" ) )
418 mrTypeModel.mbVisible = !aValue.equalsAscii( "hidden" );
419 else if( aName == "mso-wrap-style" ) mrTypeModel.maWrapStyle = aValue;
420 else if ( aName == "v-text-anchor" ) mrTypeModel.maVTextAnchor = aValue;
421 else if ( aName == "mso-wrap-distance-left" ) mrTypeModel.maWrapDistanceLeft = aValue;
422 else if ( aName == "mso-wrap-distance-right" ) mrTypeModel.maWrapDistanceRight = aValue;
423 else if ( aName == "mso-wrap-distance-top" ) mrTypeModel.maWrapDistanceTop = aValue;
424 else if ( aName == "mso-wrap-distance-bottom" ) mrTypeModel.maWrapDistanceBottom = aValue;
429 // ============================================================================
431 ShapeContext::ShapeContext( ContextHandler2Helper& rParent, ShapeBase& rShape, const AttributeList& rAttribs ) :
432 ShapeTypeContext( rParent, rShape, rAttribs ),
433 mrShape( rShape ),
434 mrShapeModel( rShape.getShapeModel() )
436 // collect shape specific attributes
437 mrShapeModel.maType = rAttribs.getXString( XML_type, OUString() );
438 // polyline path
439 setPoints( rAttribs.getString( XML_points, OUString() ) );
440 // line start and end positions
441 setFrom(rAttribs.getString(XML_from, OUString()));
442 setTo(rAttribs.getString(XML_to, OUString()));
443 setControl1(rAttribs.getString(XML_control1, OUString()));
444 setControl2(rAttribs.getString(XML_control2, OUString()));
445 setVmlPath(rAttribs.getString(XML_path, OUString()));
448 ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
450 // Excel specific shape client data
451 if( isRootElement() ) switch( nElement )
453 case VML_TOKEN( textbox ):
454 if (getParentElement() != VML_TOKEN( group ))
456 // Custom shape in Writer with a textbox are transformed into a frame
457 dynamic_cast<SimpleShape&>( mrShape ).setService(
458 "com.sun.star.text.TextFrame");
460 return new TextBoxContext( *this, mrShapeModel.createTextBox(mrShape.getTypeModel()), rAttribs,
461 mrShape.getDrawing().getFilter().getGraphicHelper());
462 case VMLX_TOKEN( ClientData ):
463 return new ClientDataContext( *this, mrShapeModel.createClientData(), rAttribs );
464 case VMLPPT_TOKEN( textdata ):
465 // Force RectangleShape, this is ugly :(
466 // and is there because of the lines above which change it to TextFrame
467 dynamic_cast< SimpleShape& >( mrShape ).setService(
468 "com.sun.star.drawing.RectangleShape");
469 mrShapeModel.maLegacyDiagramPath = getFragmentPathFromRelId(rAttribs.getString(XML_id, OUString()));
470 break;
472 // handle remaining stuff in base class
473 return ShapeTypeContext::onCreateContext( nElement, rAttribs );
476 void ShapeContext::setPoints( const OUString& rPoints )
478 mrShapeModel.maPoints.clear();
479 sal_Int32 nIndex = 0;
481 while( nIndex >= 0 )
483 sal_Int32 nX = rPoints.getToken( 0, ',', nIndex ).toInt32();
484 sal_Int32 nY = rPoints.getToken( 0, ',', nIndex ).toInt32();
485 mrShapeModel.maPoints.push_back( awt::Point( nX, nY ) );
489 void ShapeContext::setFrom( const OUString& rPoints )
491 if (!rPoints.isEmpty())
492 mrShapeModel.maFrom = rPoints;
495 void ShapeContext::setTo( const OUString& rPoints )
497 if (!rPoints.isEmpty())
498 mrShapeModel.maTo = rPoints;
501 void ShapeContext::setControl1( const OUString& rPoints )
503 if (!rPoints.isEmpty())
504 mrShapeModel.maControl1 = rPoints;
507 void ShapeContext::setControl2( const OUString& rPoints )
509 if (!rPoints.isEmpty())
510 mrShapeModel.maControl2 = rPoints;
512 void ShapeContext::setVmlPath( const OUString& rPath )
514 if (!rPath.isEmpty())
515 mrShapeModel.maVmlPath = rPath;
519 // ============================================================================
521 GroupShapeContext::GroupShapeContext( ContextHandler2Helper& rParent, GroupShape& rShape, const AttributeList& rAttribs ) :
522 ShapeContext( rParent, rShape, rAttribs ),
523 mrShapes( rShape.getChildren() )
527 ContextHandlerRef GroupShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
529 // try to create a context of an embedded shape
530 ContextHandlerRef xContext = createShapeContext( *this, mrShapes, nElement, rAttribs );
531 // handle remaining stuff of this shape in base class
532 return xContext.get() ? xContext : ShapeContext::onCreateContext( nElement, rAttribs );
535 // ============================================================================
537 RectangleShapeContext::RectangleShapeContext( ContextHandler2Helper& rParent, const AttributeList& rAttribs, RectangleShape& rShape ) :
538 ShapeContext( rParent, rShape, rAttribs )
542 ContextHandlerRef RectangleShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
544 // The parent class's context is fine
545 return ShapeContext::onCreateContext( nElement, rAttribs );
547 // ============================================================================
549 } // namespace vml
550 } // namespace oox
552 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */