Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "oox/vml/vmlshapecontext.hxx"
21 :
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"
27 :
28 : #include <osl/diagnose.h>
29 :
30 : namespace oox {
31 : namespace vml {
32 :
33 : using namespace ::com::sun::star;
34 :
35 : using ::oox::core::ContextHandler2;
36 : using ::oox::core::ContextHandler2Helper;
37 : using ::oox::core::ContextHandlerRef;
38 :
39 : namespace {
40 :
41 : /** Returns the boolean value from the specified VML attribute (if present).
42 : */
43 3986 : OptValue< bool > lclDecodeBool( const AttributeList& rAttribs, sal_Int32 nToken )
44 : {
45 3986 : OptValue< OUString > oValue = rAttribs.getString( nToken );
46 3986 : if( oValue.has() ) return OptValue< bool >( ConversionHelper::decodeBool( oValue.get() ) );
47 3050 : return OptValue< bool >();
48 : }
49 :
50 : /** Returns the percentage value from the specified VML attribute (if present).
51 : The value will be normalized (1.0 is returned for 100%).
52 : */
53 108 : OptValue< double > lclDecodePercent( const AttributeList& rAttribs, sal_Int32 nToken, double fDefValue )
54 : {
55 108 : OptValue< OUString > oValue = rAttribs.getString( nToken );
56 108 : if( oValue.has() ) return OptValue< double >( ConversionHelper::decodePercent( oValue.get(), fDefValue ) );
57 91 : return OptValue< double >();
58 : }
59 :
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'
62 : */
63 448 : OptValue< double > lclDecodeOpacity( const AttributeList& rAttribs, sal_Int32 nToken, double fDefValue )
64 : {
65 448 : OptValue< OUString > oValue = rAttribs.getString( nToken );
66 448 : double fRetval(fDefValue);
67 :
68 448 : if( oValue.has() )
69 : {
70 26 : const OUString aString(oValue.get());
71 26 : const sal_Int32 nLength(aString.getLength());
72 :
73 26 : if(nLength > 0)
74 : {
75 26 : if(aString.endsWith("f"))
76 : {
77 5 : fRetval = std::max(0.0, std::min(1.0, aString.toDouble() / 65536.0));
78 : }
79 : else
80 : {
81 21 : fRetval = ConversionHelper::decodePercent( aString, fDefValue );
82 : }
83 26 : }
84 : }
85 :
86 448 : return OptValue< double >(fRetval);
87 : }
88 :
89 : /** Returns the integer value pair from the specified VML attribute (if present).
90 : */
91 2336 : OptValue< Int32Pair > lclDecodeInt32Pair( const AttributeList& rAttribs, sal_Int32 nToken )
92 : {
93 2336 : OptValue< OUString > oValue = rAttribs.getString( nToken );
94 2336 : OptValue< Int32Pair > oRetValue;
95 2336 : if( oValue.has() )
96 : {
97 1204 : OUString aValue1, aValue2;
98 602 : ConversionHelper::separatePair( aValue1, aValue2, oValue.get(), ',' );
99 1204 : oRetValue = Int32Pair( aValue1.toInt32(), aValue2.toInt32() );
100 : }
101 2336 : return oRetValue;
102 : }
103 :
104 : /** Returns the percentage pair from the specified VML attribute (if present).
105 : */
106 148 : OptValue< DoublePair > lclDecodePercentPair( const AttributeList& rAttribs, sal_Int32 nToken )
107 : {
108 148 : OptValue< OUString > oValue = rAttribs.getString( nToken );
109 148 : OptValue< DoublePair > oRetValue;
110 148 : if( oValue.has() )
111 : {
112 12 : OUString aValue1, aValue2;
113 6 : ConversionHelper::separatePair( aValue1, aValue2, oValue.get(), ',' );
114 18 : oRetValue = DoublePair(
115 6 : ConversionHelper::decodePercent( aValue1, 0.0 ),
116 18 : ConversionHelper::decodePercent( aValue2, 0.0 ) );
117 : }
118 148 : return oRetValue;
119 : }
120 :
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.
124 : */
125 1 : bool lclDecodeVmlxBool( const OUString& rValue, bool bDefaultForEmpty )
126 : {
127 1 : if( rValue.isEmpty() ) return bDefaultForEmpty;
128 0 : sal_Int32 nToken = AttributeConversion::decodeToken( rValue );
129 : // anything else than 't' or 'True' is considered to be false, as specified
130 0 : return (nToken == XML_t) || (nToken == XML_True);
131 : }
132 :
133 : } // namespace
134 :
135 4 : ShapeLayoutContext::ShapeLayoutContext( ContextHandler2Helper& rParent, Drawing& rDrawing ) :
136 : ContextHandler2( rParent ),
137 4 : mrDrawing( rDrawing )
138 : {
139 4 : }
140 :
141 4 : ContextHandlerRef ShapeLayoutContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
142 : {
143 4 : switch( nElement )
144 : {
145 : case O_TOKEN( idmap ):
146 : {
147 4 : OUString aBlockIds = rAttribs.getString( XML_data, OUString() );
148 4 : sal_Int32 nIndex = 0;
149 12 : while( nIndex >= 0 )
150 : {
151 4 : OUString aToken = aBlockIds.getToken( 0, ' ', nIndex ).trim();
152 4 : if( !aToken.isEmpty() )
153 4 : mrDrawing.registerBlockId( aToken.toInt32() );
154 8 : }
155 : }
156 4 : break;
157 : }
158 4 : return 0;
159 : }
160 :
161 3 : ClientDataContext::ClientDataContext( ContextHandler2Helper& rParent,
162 : ClientData& rClientData, const AttributeList& rAttribs ) :
163 : ContextHandler2( rParent ),
164 3 : mrClientData( rClientData )
165 : {
166 3 : mrClientData.mnObjType = rAttribs.getToken( XML_ObjectType, XML_TOKEN_INVALID );
167 3 : }
168 :
169 19 : ContextHandlerRef ClientDataContext::onCreateContext( sal_Int32 /*nElement*/, const AttributeList& /*rAttribs*/ )
170 : {
171 19 : if( isRootElement() )
172 : {
173 19 : maElementText.clear();
174 19 : return this;
175 : }
176 0 : return 0;
177 : }
178 :
179 28 : void ClientDataContext::onCharacters( const OUString& rChars )
180 : {
181 : /* Empty but existing elements have special meaning, e.g. 'true'. Collect
182 : existing text and convert it in onEndElement(). */
183 28 : maElementText = rChars;
184 28 : }
185 :
186 22 : void ClientDataContext::onEndElement()
187 : {
188 22 : switch( getCurrentElement() )
189 : {
190 3 : case VMLX_TOKEN( Anchor ): mrClientData.maAnchor = maElementText; break;
191 0 : case VMLX_TOKEN( FmlaMacro ): mrClientData.maFmlaMacro = maElementText; break;
192 0 : case VMLX_TOKEN( FmlaPict ): mrClientData.maFmlaPict = maElementText; break;
193 0 : case VMLX_TOKEN( FmlaLink ): mrClientData.maFmlaLink = maElementText; break;
194 0 : case VMLX_TOKEN( FmlaRange ): mrClientData.maFmlaRange = maElementText; break;
195 0 : case VMLX_TOKEN( FmlaGroup ): mrClientData.maFmlaGroup = maElementText; break;
196 0 : case VMLX_TOKEN( TextHAlign ): mrClientData.mnTextHAlign = AttributeConversion::decodeToken( maElementText ); break;
197 1 : case VMLX_TOKEN( TextVAlign ): mrClientData.mnTextVAlign = AttributeConversion::decodeToken( maElementText ); break;
198 2 : case VMLX_TOKEN( Column ): mrClientData.mnCol = maElementText.toInt32(); break;
199 2 : case VMLX_TOKEN( Row ): mrClientData.mnRow = maElementText.toInt32(); break;
200 1 : case VMLX_TOKEN( Checked ): mrClientData.mnChecked = maElementText.toInt32(); break;
201 0 : case VMLX_TOKEN( DropStyle ): mrClientData.mnDropStyle = AttributeConversion::decodeToken( maElementText ); break;
202 0 : case VMLX_TOKEN( DropLines ): mrClientData.mnDropLines = maElementText.toInt32(); break;
203 0 : case VMLX_TOKEN( Val ): mrClientData.mnVal = maElementText.toInt32(); break;
204 0 : case VMLX_TOKEN( Min ): mrClientData.mnMin = maElementText.toInt32(); break;
205 0 : case VMLX_TOKEN( Max ): mrClientData.mnMax = maElementText.toInt32(); break;
206 0 : case VMLX_TOKEN( Inc ): mrClientData.mnInc = maElementText.toInt32(); break;
207 0 : case VMLX_TOKEN( Page ): mrClientData.mnPage = maElementText.toInt32(); break;
208 0 : case VMLX_TOKEN( SelType ): mrClientData.mnSelType = AttributeConversion::decodeToken( maElementText ); break;
209 0 : case VMLX_TOKEN( VTEdit ): mrClientData.mnVTEdit = maElementText.toInt32(); break;
210 0 : case VMLX_TOKEN( PrintObject ): mrClientData.mbPrintObject = lclDecodeVmlxBool( maElementText, true ); break;
211 0 : case VMLX_TOKEN( Visible ): mrClientData.mbVisible = lclDecodeVmlxBool( maElementText, true ); break;
212 0 : case VMLX_TOKEN( DDE ): mrClientData.mbDde = lclDecodeVmlxBool( maElementText, true ); break;
213 1 : case VMLX_TOKEN( NoThreeD ): mrClientData.mbNo3D = lclDecodeVmlxBool( maElementText, true ); break;
214 0 : case VMLX_TOKEN( NoThreeD2 ): mrClientData.mbNo3D2 = lclDecodeVmlxBool( maElementText, true ); break;
215 0 : case VMLX_TOKEN( MultiLine ): mrClientData.mbMultiLine = lclDecodeVmlxBool( maElementText, true ); break;
216 0 : case VMLX_TOKEN( VScroll ): mrClientData.mbVScroll = lclDecodeVmlxBool( maElementText, true ); break;
217 0 : case VMLX_TOKEN( SecretEdit ): mrClientData.mbSecretEdit = lclDecodeVmlxBool( maElementText, true ); break;
218 : }
219 22 : }
220 :
221 1168 : ShapeContextBase::ShapeContextBase( ContextHandler2Helper& rParent ) :
222 1168 : ContextHandler2( rParent )
223 : {
224 1168 : }
225 :
226 1199 : ContextHandlerRef ShapeContextBase::createShapeContext( ContextHandler2Helper& rParent,
227 : ShapeContainer& rShapes, sal_Int32 nElement, const AttributeList& rAttribs )
228 : {
229 1199 : switch( nElement )
230 : {
231 : case O_TOKEN( shapelayout ):
232 4 : return new ShapeLayoutContext( rParent, rShapes.getDrawing() );
233 :
234 : case VML_TOKEN( shapetype ):
235 201 : return new ShapeTypeContext( rParent, rShapes.createShapeType(), rAttribs );
236 : case VML_TOKEN( group ):
237 34 : return new GroupShapeContext( rParent, rShapes.createShape< GroupShape >(), rAttribs );
238 : case VML_TOKEN( shape ):
239 687 : if (rAttribs.hasAttribute(XML_path))
240 341 : return new ShapeContext( rParent, rShapes.createShape< BezierShape >(), rAttribs );
241 : else
242 346 : return new ShapeContext( rParent, rShapes.createShape< ComplexShape >(), rAttribs );
243 : case VML_TOKEN( rect ):
244 234 : return new RectangleShapeContext( rParent, rAttribs, rShapes.createShape< RectangleShape >() );
245 : case VML_TOKEN( roundrect ):
246 3 : return new ShapeContext( rParent, rShapes.createShape< RectangleShape >(), rAttribs );
247 : case VML_TOKEN( oval ):
248 2 : return new ShapeContext( rParent, rShapes.createShape< EllipseShape >(), rAttribs );
249 : case VML_TOKEN( polyline ):
250 2 : return new ShapeContext( rParent, rShapes.createShape< PolyLineShape >(), rAttribs );
251 : case VML_TOKEN( line ):
252 5 : return new ShapeContext( rParent, rShapes.createShape< LineShape >(), rAttribs );
253 : case VML_TOKEN( curve ):
254 0 : return new ShapeContext( rParent, rShapes.createShape< BezierShape >(), rAttribs );
255 :
256 : // TODO:
257 : case VML_TOKEN( arc ):
258 : case VML_TOKEN( diagram ):
259 : case VML_TOKEN( image ):
260 0 : return new ShapeContext( rParent, rShapes.createShape< ComplexShape >(), rAttribs );
261 : }
262 27 : return 0;
263 : }
264 :
265 1168 : ShapeTypeContext::ShapeTypeContext( ContextHandler2Helper& rParent, ShapeType& rShapeType, const AttributeList& rAttribs ) :
266 : ShapeContextBase( rParent ),
267 1168 : mrTypeModel( rShapeType.getTypeModel() )
268 : {
269 : // shape identifier and shape name
270 1168 : bool bHasOspid = rAttribs.hasAttribute( O_TOKEN( spid ) );
271 1168 : mrTypeModel.maShapeId = rAttribs.getXString( bHasOspid ? O_TOKEN( spid ) : XML_id, OUString() );
272 : OSL_ENSURE( !mrTypeModel.maShapeId.isEmpty(), "ShapeTypeContext::ShapeTypeContext - missing shape identifier" );
273 : // if the o:spid attribute exists, the id attribute contains the user-defined shape name
274 1168 : if( bHasOspid )
275 357 : mrTypeModel.maShapeName = rAttribs.getXString( XML_id, OUString() );
276 : // builtin shape type identifier
277 1168 : mrTypeModel.moShapeType = rAttribs.getInteger( O_TOKEN( spt ) );
278 :
279 : // coordinate system position/size, CSS style
280 1168 : mrTypeModel.moCoordPos = lclDecodeInt32Pair( rAttribs, XML_coordorigin );
281 1168 : mrTypeModel.moCoordSize = lclDecodeInt32Pair( rAttribs, XML_coordsize );
282 1168 : setStyle( rAttribs.getString( XML_style, OUString() ) );
283 1168 : if( lclDecodeBool( rAttribs, O_TOKEN( hr )).get( false ))
284 : { // MSO's handling of o:hr width is nowhere near what the spec says:
285 : // - o:hrpct is not in % but in 0.1%
286 : // - if o:hrpct is not given, 100% width is assumed
287 : // - given width is used only if explicit o:hrpct="0" is given
288 8 : OUString hrpct = rAttribs.getString( O_TOKEN( hrpct ), "1000" );
289 8 : if( hrpct != "0" )
290 8 : mrTypeModel.maWidth = OUString::number( hrpct.toInt32() / 10 ) + "%";
291 : }
292 :
293 : // stroke settings (may be overridden by v:stroke element later)
294 1168 : mrTypeModel.maStrokeModel.moStroked = lclDecodeBool( rAttribs, XML_stroked );
295 1168 : mrTypeModel.maStrokeModel.moColor = rAttribs.getString( XML_strokecolor );
296 1168 : mrTypeModel.maStrokeModel.moWeight = rAttribs.getString( XML_strokeweight );
297 :
298 : // fill settings (may be overridden by v:fill element later)
299 1168 : mrTypeModel.maFillModel.moFilled = lclDecodeBool( rAttribs, XML_filled );
300 1168 : mrTypeModel.maFillModel.moColor = rAttribs.getString( XML_fillcolor );
301 :
302 : // For roundrect we may have a arcsize attribute to read
303 1168 : mrTypeModel.maArcsize = rAttribs.getString( XML_arcsize,OUString( ) );
304 : // editas
305 1168 : mrTypeModel.maEditAs = rAttribs.getString(XML_editas, OUString());
306 1168 : }
307 :
308 1597 : ContextHandlerRef ShapeTypeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
309 : {
310 1597 : if( isRootElement() ) switch( nElement )
311 : {
312 : case VML_TOKEN( stroke ):
313 300 : mrTypeModel.maStrokeModel.moStroked.assignIfUsed( lclDecodeBool( rAttribs, XML_on ) );
314 300 : mrTypeModel.maStrokeModel.maStartArrow.moArrowType = rAttribs.getToken( XML_startarrow );
315 300 : mrTypeModel.maStrokeModel.maStartArrow.moArrowWidth = rAttribs.getToken( XML_startarrowwidth );
316 300 : mrTypeModel.maStrokeModel.maStartArrow.moArrowLength = rAttribs.getToken( XML_startarrowlength );
317 300 : mrTypeModel.maStrokeModel.maEndArrow.moArrowType = rAttribs.getToken( XML_endarrow );
318 300 : mrTypeModel.maStrokeModel.maEndArrow.moArrowWidth = rAttribs.getToken( XML_endarrowwidth );
319 300 : mrTypeModel.maStrokeModel.maEndArrow.moArrowLength = rAttribs.getToken( XML_endarrowlength );
320 300 : mrTypeModel.maStrokeModel.moColor.assignIfUsed( rAttribs.getString( XML_color ) );
321 300 : mrTypeModel.maStrokeModel.moOpacity = lclDecodeOpacity( rAttribs, XML_opacity, 1.0 );
322 300 : mrTypeModel.maStrokeModel.moWeight.assignIfUsed( rAttribs.getString( XML_weight ) );
323 300 : mrTypeModel.maStrokeModel.moDashStyle = rAttribs.getString( XML_dashstyle );
324 300 : mrTypeModel.maStrokeModel.moLineStyle = rAttribs.getToken( XML_linestyle );
325 300 : mrTypeModel.maStrokeModel.moEndCap = rAttribs.getToken( XML_endcap );
326 300 : mrTypeModel.maStrokeModel.moJoinStyle = rAttribs.getToken( XML_joinstyle );
327 300 : break;
328 : case VML_TOKEN( fill ):
329 74 : mrTypeModel.maFillModel.moFilled.assignIfUsed( lclDecodeBool( rAttribs, XML_on ) );
330 74 : mrTypeModel.maFillModel.moColor.assignIfUsed( rAttribs.getString( XML_color ) );
331 74 : mrTypeModel.maFillModel.moOpacity = lclDecodeOpacity( rAttribs, XML_opacity, 1.0 );
332 74 : mrTypeModel.maFillModel.moColor2 = rAttribs.getString( XML_color2 );
333 74 : mrTypeModel.maFillModel.moOpacity2 = lclDecodeOpacity( rAttribs, XML_opacity2, 1.0 );
334 74 : mrTypeModel.maFillModel.moType = rAttribs.getToken( XML_type );
335 74 : mrTypeModel.maFillModel.moAngle = rAttribs.getInteger( XML_angle );
336 74 : mrTypeModel.maFillModel.moFocus = lclDecodePercent( rAttribs, XML_focus, 0.0 );
337 74 : mrTypeModel.maFillModel.moFocusPos = lclDecodePercentPair( rAttribs, XML_focusposition );
338 74 : mrTypeModel.maFillModel.moFocusSize = lclDecodePercentPair( rAttribs, XML_focussize );
339 74 : mrTypeModel.maFillModel.moBitmapPath = decodeFragmentPath( rAttribs, O_TOKEN( relid ) );
340 74 : mrTypeModel.maFillModel.moRotate = lclDecodeBool( rAttribs, XML_rotate );
341 74 : break;
342 : case VML_TOKEN( imagedata ):
343 : {
344 : // shapes in docx use r:id for the relationship id
345 : // in xlsx it they use o:relid
346 157 : bool bHasORelId = rAttribs.hasAttribute( O_TOKEN( relid ) );
347 157 : mrTypeModel.moGraphicPath = decodeFragmentPath( rAttribs, bHasORelId ? O_TOKEN( relid ) : R_TOKEN( id ) );
348 157 : mrTypeModel.moGraphicTitle = rAttribs.getString( O_TOKEN( title ) );
349 : }
350 157 : break;
351 : case NMSP_vmlWord | XML_wrap:
352 53 : mrTypeModel.moWrapAnchorX = rAttribs.getString(XML_anchorx);
353 53 : mrTypeModel.moWrapAnchorY = rAttribs.getString(XML_anchory);
354 53 : mrTypeModel.moWrapType = rAttribs.getString(XML_type);
355 53 : mrTypeModel.moWrapSide = rAttribs.getString(XML_side);
356 53 : break;
357 : case VML_TOKEN( shadow ):
358 : {
359 34 : mrTypeModel.maShadowModel.mbHasShadow = true;
360 34 : mrTypeModel.maShadowModel.moShadowOn.assignIfUsed(lclDecodeBool(rAttribs, XML_on));
361 34 : mrTypeModel.maShadowModel.moColor.assignIfUsed(rAttribs.getString(XML_color));
362 34 : mrTypeModel.maShadowModel.moOffset.assignIfUsed(rAttribs.getString(XML_offset));
363 34 : mrTypeModel.maShadowModel.moOpacity = lclDecodePercent(rAttribs, XML_opacity, 1.0);
364 : }
365 34 : break;
366 : case VML_TOKEN( textpath ):
367 79 : mrTypeModel.maTextpathModel.moString.assignIfUsed(rAttribs.getString(XML_string));
368 79 : break;
369 : }
370 1597 : return 0;
371 : }
372 :
373 231 : OptValue< OUString > ShapeTypeContext::decodeFragmentPath( const AttributeList& rAttribs, sal_Int32 nToken ) const
374 : {
375 231 : OptValue< OUString > oFragmentPath;
376 462 : OptValue< OUString > oRelId = rAttribs.getString( nToken );
377 231 : if( oRelId.has() )
378 157 : oFragmentPath = getFragmentPathFromRelId( oRelId.get() );
379 462 : return oFragmentPath;
380 : }
381 :
382 1168 : void ShapeTypeContext::setStyle( const OUString& rStyle )
383 : {
384 1168 : sal_Int32 nIndex = 0;
385 8864 : while( nIndex >= 0 )
386 : {
387 13056 : OUString aName, aValue;
388 6528 : if( ConversionHelper::separatePair( aName, aValue, rStyle.getToken( 0, ';', nIndex ), ':' ) )
389 : {
390 6327 : if( aName == "position" ) mrTypeModel.maPosition = aValue;
391 5550 : else if( aName == "z-index" ) mrTypeModel.maZIndex = aValue;
392 5397 : else if( aName == "left" ) mrTypeModel.maLeft = aValue;
393 4764 : else if( aName == "top" ) mrTypeModel.maTop = aValue;
394 4175 : else if( aName == "width" ) mrTypeModel.maWidth = aValue;
395 3215 : else if( aName == "height" ) mrTypeModel.maHeight = aValue;
396 2255 : else if( aName == "margin-left" ) mrTypeModel.maMarginLeft = aValue;
397 2085 : else if( aName == "margin-top" ) mrTypeModel.maMarginTop = aValue;
398 1915 : else if( aName == "mso-position-vertical-relative" ) mrTypeModel.maPositionVerticalRelative = aValue;
399 1795 : else if( aName == "mso-position-horizontal-relative" ) mrTypeModel.maPositionHorizontalRelative = aValue;
400 1676 : else if( aName == "mso-position-horizontal" ) mrTypeModel.maPositionHorizontal = aValue;
401 1428 : else if( aName == "mso-position-vertical" ) mrTypeModel.maPositionVertical = aValue;
402 1185 : else if( aName == "mso-width-percent" ) mrTypeModel.maWidthPercent = aValue;
403 1155 : else if( aName == "mso-width-relative" ) mrTypeModel.maWidthRelative = aValue;
404 1131 : else if( aName == "mso-height-percent" ) mrTypeModel.maHeightPercent = aValue;
405 1095 : else if( aName == "mso-height-relative" ) mrTypeModel.maHeightRelative = aValue;
406 1071 : else if( aName == "mso-fit-shape-to-text" ) mrTypeModel.mbAutoHeight = true;
407 1071 : else if( aName == "rotation" ) mrTypeModel.maRotation = aValue;
408 1028 : else if( aName == "flip" ) mrTypeModel.maFlip = aValue;
409 1011 : else if( aName == "visibility" )
410 324 : mrTypeModel.mbVisible = aValue != "hidden";
411 687 : else if( aName == "mso-wrap-style" ) mrTypeModel.maWrapStyle = aValue;
412 373 : else if ( aName == "v-text-anchor" ) mrTypeModel.maVTextAnchor = aValue;
413 73 : else if ( aName == "mso-wrap-distance-left" ) mrTypeModel.maWrapDistanceLeft = aValue;
414 68 : else if ( aName == "mso-wrap-distance-right" ) mrTypeModel.maWrapDistanceRight = aValue;
415 63 : else if ( aName == "mso-wrap-distance-top" ) mrTypeModel.maWrapDistanceTop = aValue;
416 57 : else if ( aName == "mso-wrap-distance-bottom" ) mrTypeModel.maWrapDistanceBottom = aValue;
417 : }
418 6528 : }
419 1168 : }
420 :
421 967 : ShapeContext::ShapeContext( ContextHandler2Helper& rParent, ShapeBase& rShape, const AttributeList& rAttribs ) :
422 : ShapeTypeContext( rParent, rShape, rAttribs ),
423 : mrShape( rShape ),
424 967 : mrShapeModel( rShape.getShapeModel() )
425 : {
426 : // collect shape specific attributes
427 967 : mrShapeModel.maType = rAttribs.getXString( XML_type, OUString() );
428 : // polyline path
429 967 : setPoints( rAttribs.getString( XML_points, OUString() ) );
430 : // line start and end positions
431 967 : setFrom(rAttribs.getString(XML_from, OUString()));
432 967 : setTo(rAttribs.getString(XML_to, OUString()));
433 967 : setControl1(rAttribs.getString(XML_control1, OUString()));
434 967 : setControl2(rAttribs.getString(XML_control2, OUString()));
435 967 : setVmlPath(rAttribs.getString(XML_path, OUString()));
436 967 : }
437 :
438 1247 : ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
439 : {
440 : // Excel specific shape client data
441 1247 : if( isRootElement() ) switch( nElement )
442 : {
443 : case VML_TOKEN( textbox ):
444 262 : if (getParentElement() != VML_TOKEN( group ))
445 : {
446 : // Custom shape in Writer with a textbox are transformed into a frame
447 77 : dynamic_cast<SimpleShape&>( mrShape ).setService(
448 154 : "com.sun.star.text.TextFrame");
449 : }
450 185 : else if (getCurrentElement() == VML_TOKEN(rect))
451 : // Transform only rectangles into a TextShape inside a groupshape.
452 168 : dynamic_cast<SimpleShape&>(mrShape).setService("com.sun.star.drawing.TextShape");
453 262 : return new TextBoxContext( *this, mrShapeModel.createTextBox(mrShape.getTypeModel()), rAttribs,
454 262 : mrShape.getDrawing().getFilter().getGraphicHelper());
455 : case VMLX_TOKEN( ClientData ):
456 3 : return new ClientDataContext( *this, mrShapeModel.createClientData(), rAttribs );
457 : case VMLPPT_TOKEN( textdata ):
458 : // Force RectangleShape, this is ugly :(
459 : // and is there because of the lines above which change it to TextFrame
460 0 : dynamic_cast< SimpleShape& >( mrShape ).setService(
461 0 : "com.sun.star.drawing.RectangleShape");
462 0 : mrShapeModel.maLegacyDiagramPath = getFragmentPathFromRelId(rAttribs.getString(XML_id, OUString()));
463 0 : break;
464 : }
465 : // handle remaining stuff in base class
466 982 : return ShapeTypeContext::onCreateContext( nElement, rAttribs );
467 : }
468 :
469 967 : void ShapeContext::setPoints( const OUString& rPoints )
470 : {
471 967 : mrShapeModel.maPoints.clear();
472 967 : sal_Int32 nIndex = 0;
473 :
474 2903 : while( nIndex >= 0 )
475 : {
476 969 : sal_Int32 nX = rPoints.getToken( 0, ',', nIndex ).toInt32();
477 969 : sal_Int32 nY = rPoints.getToken( 0, ',', nIndex ).toInt32();
478 969 : mrShapeModel.maPoints.push_back( awt::Point( nX, nY ) );
479 : }
480 967 : }
481 :
482 967 : void ShapeContext::setFrom( const OUString& rPoints )
483 : {
484 967 : if (!rPoints.isEmpty())
485 5 : mrShapeModel.maFrom = rPoints;
486 967 : }
487 :
488 967 : void ShapeContext::setTo( const OUString& rPoints )
489 : {
490 967 : if (!rPoints.isEmpty())
491 5 : mrShapeModel.maTo = rPoints;
492 967 : }
493 :
494 967 : void ShapeContext::setControl1( const OUString& rPoints )
495 : {
496 967 : if (!rPoints.isEmpty())
497 0 : mrShapeModel.maControl1 = rPoints;
498 967 : }
499 :
500 967 : void ShapeContext::setControl2( const OUString& rPoints )
501 : {
502 967 : if (!rPoints.isEmpty())
503 0 : mrShapeModel.maControl2 = rPoints;
504 967 : }
505 967 : void ShapeContext::setVmlPath( const OUString& rPath )
506 : {
507 967 : if (!rPath.isEmpty())
508 341 : mrShapeModel.maVmlPath = rPath;
509 967 : }
510 :
511 34 : GroupShapeContext::GroupShapeContext( ContextHandler2Helper& rParent, GroupShape& rShape, const AttributeList& rAttribs ) :
512 : ShapeContext( rParent, rShape, rAttribs ),
513 34 : mrShapes( rShape.getChildren() )
514 : {
515 34 : }
516 :
517 658 : ContextHandlerRef GroupShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
518 : {
519 : // try to create a context of an embedded shape
520 658 : ContextHandlerRef xContext = createShapeContext( *this, mrShapes, nElement, rAttribs );
521 : // handle remaining stuff of this shape in base class
522 658 : return xContext.get() ? xContext : ShapeContext::onCreateContext( nElement, rAttribs );
523 : }
524 :
525 234 : RectangleShapeContext::RectangleShapeContext( ContextHandler2Helper& rParent, const AttributeList& rAttribs, RectangleShape& rShape ) :
526 234 : ShapeContext( rParent, rShape, rAttribs )
527 : {
528 234 : }
529 :
530 244 : ContextHandlerRef RectangleShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
531 : {
532 : // The parent class's context is fine
533 244 : return ShapeContext::onCreateContext( nElement, rAttribs );
534 : }
535 :
536 : } // namespace vml
537 246 : } // namespace oox
538 :
539 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|