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"
28 #include <osl/diagnose.h>
33 using namespace ::com::sun::star
;
35 using ::oox::core::ContextHandler2
;
36 using ::oox::core::ContextHandler2Helper
;
37 using ::oox::core::ContextHandlerRef
;
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
);
70 const OUString
aString(oValue
.get());
71 const sal_Int32
nLength(aString
.getLength());
75 if(aString
.endsWith("f"))
77 fRetval
= std::max(0.0, std::min(1.0, aString
.toDouble() / 65536.0));
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
;
97 OUString aValue1
, aValue2
;
98 ConversionHelper::separatePair( aValue1
, aValue2
, oValue
.get(), ',' );
99 oRetValue
= Int32Pair( aValue1
.toInt32(), aValue2
.toInt32() );
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
;
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 ) );
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
);
135 ShapeLayoutContext::ShapeLayoutContext( ContextHandler2Helper
& rParent
, Drawing
& rDrawing
) :
136 ContextHandler2( rParent
),
137 mrDrawing( rDrawing
)
141 ContextHandlerRef
ShapeLayoutContext::onCreateContext( sal_Int32 nElement
, const AttributeList
& rAttribs
)
145 case O_TOKEN( idmap
):
147 OUString aBlockIds
= rAttribs
.getString( XML_data
, OUString() );
148 sal_Int32 nIndex
= 0;
151 OUString aToken
= aBlockIds
.getToken( 0, ' ', nIndex
).trim();
152 if( !aToken
.isEmpty() )
153 mrDrawing
.registerBlockId( aToken
.toInt32() );
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();
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
)
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
);
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
);
257 case VML_TOKEN( arc
):
258 case VML_TOKEN( diagram
):
259 case VML_TOKEN( image
):
260 return new ShapeContext( rParent
, rShapes
.createShape
< ComplexShape
>(), rAttribs
);
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
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" );
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( ) );
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
);
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
);
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
) );
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
);
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);
367 case VML_TOKEN( textpath
):
368 mrTypeModel
.maTextpathModel
.moString
.assignIfUsed(rAttribs
.getString(XML_string
));
374 OptValue
< OUString
> ShapeTypeContext::decodeFragmentPath( const AttributeList
& rAttribs
, sal_Int32 nToken
) const
376 OptValue
< OUString
> oFragmentPath
;
377 OptValue
< OUString
> oRelId
= rAttribs
.getString( nToken
);
379 oFragmentPath
= getFragmentPathFromRelId( oRelId
.get() );
380 return oFragmentPath
;
383 void ShapeTypeContext::setStyle( const OUString
& rStyle
)
385 sal_Int32 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
),
425 mrShapeModel( rShape
.getShapeModel() )
427 // collect shape specific attributes
428 mrShapeModel
.maType
= rAttribs
.getXString( XML_type
, OUString() );
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()));
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;
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
);
540 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */