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