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/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"
31 // ============================================================================
33 using namespace ::com::sun::star
;
35 using ::oox::core::ContextHandler2
;
36 using ::oox::core::ContextHandler2Helper
;
37 using ::oox::core::ContextHandlerRef
;
39 // ============================================================================
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
);
72 const OUString
aString(oValue
.get());
73 const sal_Int32
nLength(aString
.getLength());
77 if(aString
.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM("f")))
79 fRetval
= std::max(0.0, std::min(1.0, aString
.toDouble() / 65536.0));
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
;
99 OUString aValue1
, aValue2
;
100 ConversionHelper::separatePair( aValue1
, aValue2
, oValue
.get(), ',' );
101 oRetValue
= Int32Pair( aValue1
.toInt32(), aValue2
.toInt32() );
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
;
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 ) );
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
);
137 // ============================================================================
139 ShapeLayoutContext::ShapeLayoutContext( ContextHandler2Helper
& rParent
, Drawing
& rDrawing
) :
140 ContextHandler2( rParent
),
141 mrDrawing( rDrawing
)
146 ContextHandlerRef
ShapeLayoutContext::onCreateContext( sal_Int32 nElement
, const AttributeList
& rAttribs
)
150 case O_TOKEN( idmap
):
152 OUString aBlockIds
= rAttribs
.getString( XML_data
, OUString() );
153 sal_Int32 nIndex
= 0;
156 OUString aToken
= aBlockIds
.getToken( 0, ' ', nIndex
).trim();
157 if( !aToken
.isEmpty() )
158 mrDrawing
.registerBlockId( aToken
.toInt32() );
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();
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
)
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
);
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
);
266 case VML_TOKEN( arc
):
267 case VML_TOKEN( diagram
):
268 case VML_TOKEN( image
):
269 return new ShapeContext( rParent
, rShapes
.createShape
< ComplexShape
>(), rAttribs
);
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
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" );
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
);
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
);
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
) );
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
);
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);
375 case VML_TOKEN( textpath
):
376 mrTypeModel
.maTextpathModel
.moString
.assignIfUsed(rAttribs
.getString(XML_string
));
382 OptValue
< OUString
> ShapeTypeContext::decodeFragmentPath( const AttributeList
& rAttribs
, sal_Int32 nToken
) const
384 OptValue
< OUString
> oFragmentPath
;
385 OptValue
< OUString
> oRelId
= rAttribs
.getString( nToken
);
387 oFragmentPath
= getFragmentPathFromRelId( oRelId
.get() );
388 return oFragmentPath
;
391 void ShapeTypeContext::setStyle( const OUString
& rStyle
)
393 sal_Int32 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
),
434 mrShapeModel( rShape
.getShapeModel() )
436 // collect shape specific attributes
437 mrShapeModel
.maType
= rAttribs
.getXString( XML_type
, OUString() );
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()));
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;
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 // ============================================================================
552 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */