1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: vmldrawingfragmenthandler.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/vml/vmlshapecontext.hxx"
32 #include "oox/vml/vmlshape.hxx"
33 #include "oox/vml/vmlshapecontainer.hxx"
35 using ::rtl::OUString
;
36 using ::com::sun::star::awt::Point
;
37 using ::oox::core::ContextHandler2
;
38 using ::oox::core::ContextHandler2Helper
;
39 using ::oox::core::ContextHandlerRef
;
44 // ============================================================================
48 bool lclSeparateValue( OUString
& orName
, OUString
& orValue
, const OUString
& rAttrib
, sal_Unicode cSep
= ':' )
50 sal_Int32 nSepPos
= rAttrib
.indexOf( cSep
);
51 if( nSepPos
<= 0 ) return false;
52 orName
= rAttrib
.copy( 0, nSepPos
).trim();
53 orValue
= rAttrib
.copy( nSepPos
+ 1 ).trim();
54 return (orName
.getLength() > 0) && (orValue
.getLength() > 0);
57 /** Returns the boolean value from the passed string (supported: f, t, False, True).
58 @param bDefaultForEmpty Default value for the empty string.
60 bool lclDecodeBool( const OUString
& rValue
, bool bDefaultForEmpty
)
62 if( rValue
.getLength() == 0 ) return bDefaultForEmpty
;
63 // anything else than 't' or 'True' is considered to be false, as specified
64 return ((rValue
.getLength() == 1) && (rValue
[ 0 ] == 't')) || (rValue
== CREATE_OUSTRING( "True" ));
69 // ============================================================================
71 ShapeClientDataContext::ShapeClientDataContext( ContextHandler2Helper
& rParent
,
72 const AttributeList
& rAttribs
, ShapeClientData
& rClientData
) :
73 ContextHandler2( rParent
),
74 mrClientData( rClientData
)
76 mrClientData
.mnObjType
= rAttribs
.getToken( XML_ObjectType
, XML_TOKEN_INVALID
);
79 ContextHandlerRef
ShapeClientDataContext::onCreateContext( sal_Int32
/*nElement*/, const AttributeList
& /*rAttribs*/ )
81 return isRootElement() ? this : 0;
84 void ShapeClientDataContext::onEndElement( const OUString
& rChars
)
86 switch( getCurrentElement() )
88 case VMLX_TOKEN( Anchor
): mrClientData
.maAnchor
= rChars
; break;
89 case VMLX_TOKEN( FmlaLink
): mrClientData
.maLinkedCell
= rChars
; break;
90 case VMLX_TOKEN( FmlaPict
): mrClientData
.maPictureLink
= rChars
; break;
91 case VMLX_TOKEN( FmlaRange
): mrClientData
.maSourceRange
= rChars
; break;
92 case VMLX_TOKEN( PrintObject
): mrClientData
.mbPrintObject
= lclDecodeBool( rChars
, true ); break;
96 // ============================================================================
98 ShapeContextBase::ShapeContextBase( ContextHandler2Helper
& rParent
) :
99 ContextHandler2( rParent
)
103 /*static*/ ContextHandlerRef
ShapeContextBase::createContext( ContextHandler2Helper
& rParent
,
104 sal_Int32 nElement
, const AttributeList
& rAttribs
, ShapeContainer
& rShapes
)
108 case VML_TOKEN( shapetype
):
109 return new ShapeTypeContext( rParent
, rAttribs
, rShapes
.createShapeType() );
110 case VML_TOKEN( group
):
111 return new GroupShapeContext( rParent
, rAttribs
, rShapes
.createShape
< GroupShape
>() );
112 case VML_TOKEN( shape
):
113 return new ShapeContext( rParent
, rAttribs
, rShapes
.createShape
< ComplexShape
>() );
114 case VML_TOKEN( rect
):
115 case VML_TOKEN( roundrect
):
116 return new ShapeContext( rParent
, rAttribs
, rShapes
.createShape
< RectangleShape
>() );
117 case VML_TOKEN( oval
):
118 return new ShapeContext( rParent
, rAttribs
, rShapes
.createShape
< EllipseShape
>() );
119 case VML_TOKEN( polyline
):
120 return new ShapeContext( rParent
, rAttribs
, rShapes
.createShape
< PolyLineShape
>() );
123 case VML_TOKEN( arc
):
124 case VML_TOKEN( curve
):
125 case VML_TOKEN( line
):
126 case VML_TOKEN( diagram
):
127 case VML_TOKEN( image
):
128 return new ShapeContext( rParent
, rAttribs
, rShapes
.createShape
< ComplexShape
>() );
133 // ============================================================================
135 ShapeTypeContext::ShapeTypeContext( ContextHandler2Helper
& rParent
, const AttributeList
& rAttribs
, ShapeType
& rShapeType
) :
136 ShapeContextBase( rParent
),
137 mrTypeModel( rShapeType
.getTypeModel() )
139 // shape identifier and shape name
140 bool bHasOspid
= rAttribs
.hasAttribute( O_TOKEN( spid
) );
141 mrTypeModel
.maShapeId
= rAttribs
.getXString( bHasOspid
? O_TOKEN( spid
) : XML_id
, OUString() );
142 OSL_ENSURE( mrTypeModel
.maShapeId
.getLength() > 0, "ShapeTypeContext::ShapeTypeContext - missing shape identifier" );
143 // if the o:spid attribute exists, the id attribute contains the user-defined shape name
145 mrTypeModel
.maName
= rAttribs
.getXString( XML_id
, OUString() );
146 // builtin shape type identifier
147 mrTypeModel
.monShapeType
= rAttribs
.getInteger( O_TOKEN( spt
) );
148 // coordinate system position/size
149 setCoordOrigin( rAttribs
.getString( XML_coordorigin
, OUString() ) );
150 setCoordSize( rAttribs
.getString( XML_coordsize
, OUString() ) );
152 setStyle( rAttribs
.getString( XML_style
, OUString() ) );
154 mrTypeModel
.mobStroked
= rAttribs
.getBool( XML_stroked
);
155 mrTypeModel
.moStrokeColor
= rAttribs
.getString( XML_strokecolor
);
157 mrTypeModel
.mobFilled
= rAttribs
.getBool( XML_filled
);
158 mrTypeModel
.moFillColor
= rAttribs
.getString( XML_fillcolor
);
161 ContextHandlerRef
ShapeTypeContext::onCreateContext( sal_Int32 nElement
, const AttributeList
& rAttribs
)
163 if( isRootElement() ) switch( nElement
)
165 case VML_TOKEN( imagedata
):
166 OptValue
< OUString
> oGraphicRelId
= rAttribs
.getString( O_TOKEN( relid
) );
167 if( oGraphicRelId
.has() )
168 mrTypeModel
.moGraphicPath
= getFragmentPathFromRelId( oGraphicRelId
.get() );
169 mrTypeModel
.moGraphicTitle
= rAttribs
.getString( O_TOKEN( title
) );
175 void ShapeTypeContext::setCoordOrigin( const OUString
& rCoordOrigin
)
177 OUString aCoordL
, aCoordT
;
178 if( lclSeparateValue( aCoordL
, aCoordT
, rCoordOrigin
, ',' ) )
180 mrTypeModel
.monCoordLeft
= aCoordL
.toInt32();
181 mrTypeModel
.monCoordTop
= aCoordT
.toInt32();
185 void ShapeTypeContext::setCoordSize( const OUString
& rCoordSize
)
187 OUString aCoordW
, aCoordH
;
188 if( lclSeparateValue( aCoordW
, aCoordH
, rCoordSize
, ',' ) )
190 mrTypeModel
.monCoordWidth
= aCoordW
.toInt32();
191 mrTypeModel
.monCoordHeight
= aCoordH
.toInt32();
195 void ShapeTypeContext::setStyle( const OUString
& rStyle
)
197 sal_Int32 nIndex
= 0;
200 OUString aName
, aValue
;
201 if( lclSeparateValue( aName
, aValue
, rStyle
.getToken( 0, ';', nIndex
) ) )
203 if( aName
.equalsAscii( "position" ) ) mrTypeModel
.maPosition
= aValue
;
204 else if( aName
.equalsAscii( "left" ) ) mrTypeModel
.maLeft
= aValue
;
205 else if( aName
.equalsAscii( "top" ) ) mrTypeModel
.maTop
= aValue
;
206 else if( aName
.equalsAscii( "width" ) ) mrTypeModel
.maWidth
= aValue
;
207 else if( aName
.equalsAscii( "height" ) ) mrTypeModel
.maHeight
= aValue
;
208 else if( aName
.equalsAscii( "margin-left" ) ) mrTypeModel
.maMarginLeft
= aValue
;
209 else if( aName
.equalsAscii( "margin-top" ) ) mrTypeModel
.maMarginTop
= aValue
;
214 // ============================================================================
216 ShapeContext::ShapeContext( ContextHandler2Helper
& rParent
, const AttributeList
& rAttribs
, ShapeBase
& rShape
) :
217 ShapeTypeContext( rParent
, rAttribs
, rShape
),
218 mrShapeModel( rShape
.getShapeModel() )
220 // collect shape specific attributes
221 mrShapeModel
.maType
= rAttribs
.getXString( XML_type
, OUString() );
223 setPoints( rAttribs
.getString( XML_points
, OUString() ) );
226 ContextHandlerRef
ShapeContext::onCreateContext( sal_Int32 nElement
, const AttributeList
& rAttribs
)
228 // Excel specific shape client data
229 if( isRootElement() && (nElement
== VMLX_TOKEN( ClientData
)) )
230 return new ShapeClientDataContext( *this, rAttribs
, mrShapeModel
.createClientData() );
231 // handle remaining stuff in base class
232 return ShapeTypeContext::onCreateContext( nElement
, rAttribs
);
235 void ShapeContext::setPoints( const OUString
& rPoints
)
237 mrShapeModel
.maPoints
.clear();
238 sal_Int32 nIndex
= 0;
241 sal_Int32 nX
= rPoints
.getToken( 0, ',', nIndex
).toInt32();
242 sal_Int32 nY
= rPoints
.getToken( 0, ',', nIndex
).toInt32();
243 mrShapeModel
.maPoints
.push_back( Point( nX
, nY
) );
247 // ============================================================================
249 GroupShapeContext::GroupShapeContext( ContextHandler2Helper
& rParent
, const AttributeList
& rAttribs
, GroupShape
& rShape
) :
250 ShapeContext( rParent
, rAttribs
, rShape
),
251 mrShapes( rShape
.getChildren() )
255 ContextHandlerRef
GroupShapeContext::onCreateContext( sal_Int32 nElement
, const AttributeList
& rAttribs
)
257 // try to create a context of an embedded shape
258 ContextHandlerRef xContext
= ShapeContextBase::createContext( *this, nElement
, rAttribs
, mrShapes
);
259 // handle remaining stuff of this shape in base class
260 return xContext
.get() ? xContext
: ShapeContext::onCreateContext( nElement
, rAttribs
);
263 // ============================================================================