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/export/vmlexport.hxx>
21 :
22 : #include <oox/token/tokens.hxx>
23 :
24 : #include <rtl/strbuf.hxx>
25 : #include <rtl/ustring.hxx>
26 :
27 : #include <tools/stream.hxx>
28 : #include <svx/svdotext.hxx>
29 : #include <vcl/cvtgrf.hxx>
30 : #include <filter/msfilter/msdffimp.hxx>
31 : #include <filter/msfilter/escherex.hxx>
32 :
33 : #include <com/sun/star/text/HoriOrientation.hpp>
34 : #include <com/sun/star/text/VertOrientation.hpp>
35 : #include <com/sun/star/text/RelOrientation.hpp>
36 :
37 : #include <cstdio>
38 :
39 :
40 : using namespace sax_fastparser;
41 : using namespace oox::vml;
42 : using namespace com::sun::star;
43 :
44 0 : VMLExport::VMLExport( ::sax_fastparser::FSHelperPtr pSerializer, VMLTextExport* pTextExport )
45 0 : : EscherEx( EscherExGlobalRef(new EscherExGlobal(0)), 0, /*bOOXML=*/true )
46 : , m_pSerializer( pSerializer )
47 : , m_pTextExport( pTextExport )
48 : , m_eHOri( 0 )
49 : , m_eVOri( 0 )
50 : , m_eHRel( 0 )
51 : , m_eVRel( 0 )
52 : , m_pNdTopLeft( 0 )
53 : , m_pSdrObject( 0 )
54 : , m_pShapeAttrList( NULL )
55 : , m_nShapeType( ESCHER_ShpInst_Nil )
56 : , m_nShapeFlags(0)
57 0 : , m_pShapeStyle( new OStringBuffer( 200 ) )
58 0 : , m_pShapeTypeWritten( new bool[ ESCHER_ShpInst_COUNT ] )
59 : {
60 0 : mnGroupLevel = 1;
61 0 : memset( m_pShapeTypeWritten, 0, ESCHER_ShpInst_COUNT * sizeof( bool ) );
62 0 : }
63 :
64 0 : void VMLExport::SetFS( ::sax_fastparser::FSHelperPtr pSerializer )
65 : {
66 0 : m_pSerializer = pSerializer;
67 0 : }
68 :
69 0 : VMLExport::~VMLExport()
70 : {
71 0 : delete mpOutStrm, mpOutStrm = NULL;
72 0 : delete m_pShapeStyle, m_pShapeStyle = NULL;
73 0 : delete[] m_pShapeTypeWritten, m_pShapeTypeWritten = NULL;
74 0 : }
75 :
76 0 : void VMLExport::OpenContainer( sal_uInt16 nEscherContainer, int nRecInstance )
77 : {
78 0 : EscherEx::OpenContainer( nEscherContainer, nRecInstance );
79 :
80 0 : if ( nEscherContainer == ESCHER_SpContainer )
81 : {
82 : // opening a shape container
83 : #if OSL_DEBUG_LEVEL > 0
84 : if ( m_nShapeType != ESCHER_ShpInst_Nil )
85 : fprintf( stderr, "Warning! VMLExport::OpenContainer(): opening shape inside a shape.\n" );
86 : #endif
87 0 : m_nShapeType = ESCHER_ShpInst_Nil;
88 0 : m_pShapeAttrList = m_pSerializer->createAttrList();
89 :
90 0 : if ( !m_pShapeStyle->isEmpty() )
91 0 : m_pShapeStyle->makeStringAndClear();
92 :
93 0 : m_pShapeStyle->ensureCapacity( 200 );
94 :
95 : // postpone the output so that we are able to write even the elements
96 : // that we learn inside Commit()
97 0 : m_pSerializer->mark();
98 : }
99 0 : }
100 :
101 0 : void VMLExport::CloseContainer()
102 : {
103 0 : if ( mRecTypes.back() == ESCHER_SpContainer )
104 : {
105 : // write the shape now when we have all the info
106 0 : sal_Int32 nShapeElement = StartShape();
107 :
108 0 : m_pSerializer->mergeTopMarks();
109 :
110 0 : EndShape( nShapeElement );
111 :
112 : // cleanup
113 0 : m_nShapeType = ESCHER_ShpInst_Nil;
114 0 : m_pShapeAttrList = NULL;
115 : }
116 :
117 0 : EscherEx::CloseContainer();
118 0 : }
119 :
120 0 : sal_uInt32 VMLExport::EnterGroup( const OUString& rShapeName, const Rectangle* pRect )
121 : {
122 0 : sal_uInt32 nShapeId = GenerateShapeId();
123 :
124 0 : OStringBuffer aStyle( 200 );
125 0 : FastAttributeList *pAttrList = m_pSerializer->createAttrList();
126 :
127 0 : pAttrList->add( XML_id, ShapeIdString( nShapeId ) );
128 :
129 0 : if ( rShapeName.getLength() )
130 0 : pAttrList->add( XML_alt, OUStringToOString( rShapeName, RTL_TEXTENCODING_UTF8 ) );
131 :
132 0 : bool rbAbsolutePos = true;
133 : //editAs
134 0 : OUString rEditAs = EscherEx::GetEditAs();
135 0 : if (!rEditAs.isEmpty())
136 : {
137 0 : pAttrList->add(XML_editas, OUStringToOString( rEditAs, RTL_TEXTENCODING_UTF8 ));
138 0 : rbAbsolutePos = false;
139 : }
140 :
141 : // style
142 0 : if ( pRect )
143 0 : AddRectangleDimensions( aStyle, *pRect, rbAbsolutePos );
144 :
145 0 : if ( !aStyle.isEmpty() )
146 0 : pAttrList->add( XML_style, aStyle.makeStringAndClear() );
147 :
148 : // coordorigin/coordsize
149 0 : if ( pRect && ( mnGroupLevel == 1 ) )
150 : {
151 : pAttrList->add( XML_coordorigin,
152 0 : OStringBuffer( 20 ).append( sal_Int32( pRect->Left() ) )
153 0 : .append( "," ).append( sal_Int32( pRect->Top() ) )
154 0 : .makeStringAndClear() );
155 :
156 : pAttrList->add( XML_coordsize,
157 0 : OStringBuffer( 20 ).append( sal_Int32( pRect->Right() ) - sal_Int32( pRect->Left() ) )
158 0 : .append( "," ).append( sal_Int32( pRect->Bottom() ) - sal_Int32( pRect->Top() ) )
159 0 : .makeStringAndClear() );
160 : }
161 :
162 0 : m_pSerializer->startElementNS( XML_v, XML_group, XFastAttributeListRef( pAttrList ) );
163 :
164 0 : mnGroupLevel++;
165 0 : return nShapeId;
166 : }
167 :
168 0 : void VMLExport::LeaveGroup()
169 : {
170 0 : --mnGroupLevel;
171 0 : m_pSerializer->endElementNS( XML_v, XML_group );
172 0 : }
173 :
174 0 : void VMLExport::AddShape( sal_uInt32 nShapeType, sal_uInt32 nShapeFlags, sal_uInt32 nShapeId )
175 : {
176 0 : m_nShapeType = nShapeType;
177 0 : m_nShapeFlags = nShapeFlags;
178 : // If shape is a watermark object - should keep the original shape's name
179 : // because Microsoft detects if it is a watermark by the actual name
180 0 : if (!IsWaterMarkShape(m_pSdrObject->GetName()))
181 : {
182 : // Not a watermark object
183 0 : m_pShapeAttrList->add( XML_id, ShapeIdString( nShapeId ) );
184 : }
185 : else
186 : {
187 : // A watermark object - store the optional shape ID also ('o:spid')
188 0 : m_pShapeAttrList->add( XML_id, OUStringToOString(m_pSdrObject->GetName(), RTL_TEXTENCODING_UTF8) );
189 : }
190 0 : }
191 :
192 0 : bool VMLExport::IsWaterMarkShape(const OUString& rStr)
193 : {
194 0 : if (rStr.isEmpty() ) return false;
195 :
196 0 : if (rStr.match(OUString("PowerPlusWaterMarkObject")) || rStr.match(OUString("WordPictureWatermark")))
197 0 : return true;
198 : else
199 0 : return false;
200 : }
201 :
202 0 : static void impl_AddArrowHead( sax_fastparser::FastAttributeList *pAttrList, sal_Int32 nElement, sal_uInt32 nValue )
203 : {
204 0 : if ( !pAttrList )
205 0 : return;
206 :
207 0 : const char *pArrowHead = NULL;
208 0 : switch ( nValue )
209 : {
210 0 : case ESCHER_LineNoEnd: pArrowHead = "none"; break;
211 0 : case ESCHER_LineArrowEnd: pArrowHead = "block"; break;
212 0 : case ESCHER_LineArrowStealthEnd: pArrowHead = "classic"; break;
213 0 : case ESCHER_LineArrowDiamondEnd: pArrowHead = "diamond"; break;
214 0 : case ESCHER_LineArrowOvalEnd: pArrowHead = "oval"; break;
215 0 : case ESCHER_LineArrowOpenEnd: pArrowHead = "open"; break;
216 : }
217 :
218 0 : if ( pArrowHead )
219 0 : pAttrList->add( nElement, pArrowHead );
220 : }
221 :
222 0 : static void impl_AddArrowLength( sax_fastparser::FastAttributeList *pAttrList, sal_Int32 nElement, sal_uInt32 nValue )
223 : {
224 0 : if ( !pAttrList )
225 0 : return;
226 :
227 0 : const char *pArrowLength = NULL;
228 0 : switch ( nValue )
229 : {
230 0 : case ESCHER_LineShortArrow: pArrowLength = "short"; break;
231 0 : case ESCHER_LineMediumLenArrow: pArrowLength = "medium"; break;
232 0 : case ESCHER_LineLongArrow: pArrowLength = "long"; break;
233 : }
234 :
235 0 : if ( pArrowLength )
236 0 : pAttrList->add( nElement, pArrowLength );
237 : }
238 :
239 0 : static void impl_AddArrowWidth( sax_fastparser::FastAttributeList *pAttrList, sal_Int32 nElement, sal_uInt32 nValue )
240 : {
241 0 : if ( !pAttrList )
242 0 : return;
243 :
244 0 : const char *pArrowWidth = NULL;
245 0 : switch ( nValue )
246 : {
247 0 : case ESCHER_LineNarrowArrow: pArrowWidth = "narrow"; break;
248 0 : case ESCHER_LineMediumWidthArrow: pArrowWidth = "medium"; break;
249 0 : case ESCHER_LineWideArrow: pArrowWidth = "wide"; break;
250 : }
251 :
252 0 : if ( pArrowWidth )
253 0 : pAttrList->add( nElement, pArrowWidth );
254 : }
255 :
256 0 : static void impl_AddBool( sax_fastparser::FastAttributeList *pAttrList, sal_Int32 nElement, bool bValue )
257 : {
258 0 : if ( !pAttrList )
259 0 : return;
260 :
261 0 : pAttrList->add( nElement, bValue? "t": "f" );
262 : }
263 :
264 0 : static void impl_AddColor( sax_fastparser::FastAttributeList *pAttrList, sal_Int32 nElement, sal_uInt32 nColor )
265 : {
266 : #if OSL_DEBUG_LEVEL > 0
267 : if ( nColor & 0xFF000000 )
268 : fprintf( stderr, "TODO: this is not a RGB value!\n" );
269 : #endif
270 :
271 0 : if ( !pAttrList || ( nColor & 0xFF000000 ) )
272 0 : return;
273 :
274 0 : nColor = ( ( nColor & 0xFF ) << 16 ) + ( nColor & 0xFF00 ) + ( ( nColor & 0xFF0000 ) >> 16 );
275 :
276 0 : const char *pColor = NULL;
277 : char pRgbColor[10];
278 0 : switch ( nColor )
279 : {
280 0 : case 0x000000: pColor = "black"; break;
281 0 : case 0xC0C0C0: pColor = "silver"; break;
282 0 : case 0x808080: pColor = "gray"; break;
283 0 : case 0xFFFFFF: pColor = "white"; break;
284 0 : case 0x800000: pColor = "maroon"; break;
285 0 : case 0xFF0000: pColor = "red"; break;
286 0 : case 0x800080: pColor = "purple"; break;
287 0 : case 0xFF00FF: pColor = "fuchsia"; break;
288 0 : case 0x008000: pColor = "green"; break;
289 0 : case 0x00FF00: pColor = "lime"; break;
290 0 : case 0x808000: pColor = "olive"; break;
291 0 : case 0xFFFF00: pColor = "yellow"; break;
292 0 : case 0x000080: pColor = "navy"; break;
293 0 : case 0x0000FF: pColor = "blue"; break;
294 0 : case 0x008080: pColor = "teal"; break;
295 0 : case 0x00FFFF: pColor = "aqua"; break;
296 : default:
297 : {
298 0 : snprintf( pRgbColor, sizeof( pRgbColor ), "#%06x", static_cast< unsigned int >( nColor ) ); // not too handy to use OString::valueOf() here :-(
299 0 : pColor = pRgbColor;
300 : }
301 0 : break;
302 : }
303 :
304 0 : pAttrList->add( nElement, pColor );
305 : }
306 :
307 0 : static void impl_AddInt( sax_fastparser::FastAttributeList *pAttrList, sal_Int32 nElement, sal_uInt32 nValue )
308 : {
309 0 : if ( !pAttrList )
310 0 : return;
311 :
312 0 : pAttrList->add( nElement, OString::number( nValue ).getStr() );
313 : }
314 :
315 0 : inline sal_uInt16 impl_GetUInt16( const sal_uInt8* &pVal )
316 : {
317 0 : sal_uInt16 nRet = *pVal++;
318 0 : nRet += ( *pVal++ ) << 8;
319 0 : return nRet;
320 : }
321 :
322 0 : inline sal_Int32 impl_GetPointComponent( const sal_uInt8* &pVal, sal_uInt16 nPointSize )
323 : {
324 0 : sal_Int32 nRet = 0;
325 0 : if ( ( nPointSize == 0xfff0 ) || ( nPointSize == 4 ) )
326 : {
327 0 : sal_uInt16 nUnsigned = *pVal++;
328 0 : nUnsigned += ( *pVal++ ) << 8;
329 :
330 0 : nRet = sal_Int16( nUnsigned );
331 : }
332 0 : else if ( nPointSize == 8 )
333 : {
334 0 : sal_uInt32 nUnsigned = *pVal++;
335 0 : nUnsigned += ( *pVal++ ) << 8;
336 0 : nUnsigned += ( *pVal++ ) << 16;
337 0 : nUnsigned += ( *pVal++ ) << 24;
338 :
339 0 : nRet = nUnsigned;
340 : }
341 :
342 0 : return nRet;
343 : }
344 :
345 0 : void VMLExport::AddSdrObjectVMLObject( const SdrObject& rObj)
346 : {
347 0 : m_pSdrObject = &rObj;
348 0 : }
349 0 : void VMLExport::Commit( EscherPropertyContainer& rProps, const Rectangle& rRect )
350 : {
351 0 : if ( m_nShapeType == ESCHER_ShpInst_Nil )
352 0 : return;
353 :
354 : // postpone the output of the embedded elements so that they are written
355 : // inside the shapes
356 0 : m_pSerializer->mark();
357 :
358 : // dimensions
359 0 : if ( m_nShapeType == ESCHER_ShpInst_Line )
360 0 : AddLineDimensions( rRect );
361 : else
362 0 : AddRectangleDimensions( *m_pShapeStyle, rRect );
363 :
364 : // properties
365 : bool bAlreadyWritten[ 0xFFF ];
366 0 : memset( bAlreadyWritten, 0, sizeof( bAlreadyWritten ) );
367 0 : const EscherProperties &rOpts = rProps.GetOpts();
368 0 : for ( EscherProperties::const_iterator it = rOpts.begin(); it != rOpts.end(); ++it )
369 : {
370 0 : sal_uInt16 nId = ( it->nPropId & 0x0FFF );
371 :
372 0 : if ( bAlreadyWritten[ nId ] )
373 0 : continue;
374 :
375 0 : switch ( nId )
376 : {
377 : case ESCHER_Prop_WrapText: // 133
378 : {
379 0 : const char *pWrapType = NULL;
380 0 : switch ( it->nPropValue )
381 : {
382 : case ESCHER_WrapSquare:
383 0 : case ESCHER_WrapByPoints: pWrapType = "square"; break; // these two are equivalent according to the docu
384 0 : case ESCHER_WrapNone: pWrapType = "none"; break;
385 0 : case ESCHER_WrapTopBottom: pWrapType = "topAndBottom"; break;
386 0 : case ESCHER_WrapThrough: pWrapType = "through"; break;
387 : }
388 0 : if ( pWrapType )
389 : m_pSerializer->singleElementNS( XML_w10, XML_wrap,
390 : XML_type, pWrapType,
391 0 : FSEND );
392 : }
393 0 : bAlreadyWritten[ ESCHER_Prop_WrapText ] = true;
394 0 : break;
395 :
396 : // coordorigin
397 : case ESCHER_Prop_geoLeft: // 320
398 : case ESCHER_Prop_geoTop: // 321
399 : {
400 0 : sal_uInt32 nLeft = 0, nTop = 0;
401 :
402 0 : if ( nId == ESCHER_Prop_geoLeft )
403 : {
404 0 : nLeft = it->nPropValue;
405 0 : rProps.GetOpt( ESCHER_Prop_geoTop, nTop );
406 : }
407 : else
408 : {
409 0 : nTop = it->nPropValue;
410 0 : rProps.GetOpt( ESCHER_Prop_geoLeft, nLeft );
411 : }
412 0 : if(nTop!=0 && nLeft!=0)
413 : m_pShapeAttrList->add( XML_coordorigin,
414 0 : OStringBuffer( 20 ).append( sal_Int32( nLeft ) )
415 0 : .append( "," ).append( sal_Int32( nTop ) )
416 0 : .makeStringAndClear() );
417 : }
418 0 : bAlreadyWritten[ ESCHER_Prop_geoLeft ] = true;
419 0 : bAlreadyWritten[ ESCHER_Prop_geoTop ] = true;
420 0 : break;
421 :
422 : // coordsize
423 : case ESCHER_Prop_geoRight: // 322
424 : case ESCHER_Prop_geoBottom: // 323
425 : {
426 0 : sal_uInt32 nLeft = 0, nRight = 0, nTop = 0, nBottom = 0;
427 0 : rProps.GetOpt( ESCHER_Prop_geoLeft, nLeft );
428 0 : rProps.GetOpt( ESCHER_Prop_geoTop, nTop );
429 :
430 0 : if ( nId == ESCHER_Prop_geoRight )
431 : {
432 0 : nRight = it->nPropValue;
433 0 : rProps.GetOpt( ESCHER_Prop_geoBottom, nBottom );
434 : }
435 : else
436 : {
437 0 : nBottom = it->nPropValue;
438 0 : rProps.GetOpt( ESCHER_Prop_geoRight, nRight );
439 : }
440 :
441 0 : if(nTop!=0 && nLeft!=0 && nBottom!=0 && nRight!=0 )
442 : m_pShapeAttrList->add( XML_coordsize,
443 0 : OStringBuffer( 20 ).append( sal_Int32( nRight ) - sal_Int32( nLeft ) )
444 0 : .append( "," ).append( sal_Int32( nBottom ) - sal_Int32( nTop ) )
445 0 : .makeStringAndClear() );
446 : }
447 0 : bAlreadyWritten[ ESCHER_Prop_geoRight ] = true;
448 0 : bAlreadyWritten[ ESCHER_Prop_geoBottom ] = true;
449 0 : break;
450 :
451 : case ESCHER_Prop_pVertices: // 325
452 : case ESCHER_Prop_pSegmentInfo: // 326
453 : {
454 : EscherPropSortStruct aVertices;
455 : EscherPropSortStruct aSegments;
456 :
457 0 : if ( rProps.GetOpt( ESCHER_Prop_pVertices, aVertices ) &&
458 0 : rProps.GetOpt( ESCHER_Prop_pSegmentInfo, aSegments ) )
459 : {
460 0 : const sal_uInt8 *pVerticesIt = aVertices.pBuf + 6;
461 0 : const sal_uInt8 *pSegmentIt = aSegments.pBuf;
462 0 : OStringBuffer aPath( 512 );
463 :
464 0 : sal_uInt16 nPointSize = aVertices.pBuf[4] + ( aVertices.pBuf[5] << 8 );
465 :
466 : // number of segments
467 0 : sal_uInt16 nSegments = impl_GetUInt16( pSegmentIt );
468 0 : pSegmentIt += 4;
469 :
470 0 : for ( ; nSegments; --nSegments )
471 : {
472 0 : sal_uInt16 nSeg = impl_GetUInt16( pSegmentIt );
473 0 : switch ( nSeg )
474 : {
475 : case 0x4000: // moveto
476 : {
477 0 : sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nPointSize );
478 0 : sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nPointSize );
479 0 : if (nX >= 0 && nY >= 0 )
480 0 : aPath.append( "m" ).append( nX ).append( "," ).append( nY );
481 : }
482 0 : break;
483 : case 0xb300:
484 : case 0xac00:
485 0 : break;
486 : case 0x0001: // lineto
487 : {
488 0 : sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nPointSize );
489 0 : sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nPointSize );
490 0 : aPath.append( "l" ).append( nX ).append( "," ).append( nY );
491 : }
492 0 : break;
493 : case 0x2001: // curveto
494 : {
495 0 : sal_Int32 nX1 = impl_GetPointComponent( pVerticesIt, nPointSize );
496 0 : sal_Int32 nY1 = impl_GetPointComponent( pVerticesIt, nPointSize );
497 0 : sal_Int32 nX2 = impl_GetPointComponent( pVerticesIt, nPointSize );
498 0 : sal_Int32 nY2 = impl_GetPointComponent( pVerticesIt, nPointSize );
499 0 : sal_Int32 nX3 = impl_GetPointComponent( pVerticesIt, nPointSize );
500 0 : sal_Int32 nY3 = impl_GetPointComponent( pVerticesIt, nPointSize );
501 0 : aPath.append( "c" ).append( nX1 ).append( "," ).append( nY1 ).append( "," )
502 0 : .append( nX2 ).append( "," ).append( nY2 ).append( "," )
503 0 : .append( nX3 ).append( "," ).append( nY3 );
504 : }
505 0 : break;
506 : case 0xaa00: // nofill
507 0 : aPath.append( "nf" );
508 0 : break;
509 : case 0xab00: // nostroke
510 0 : aPath.append( "ns" );
511 0 : break;
512 : case 0x6001: // close
513 0 : aPath.append( "x" );
514 0 : break;
515 : case 0x8000: // end
516 0 : aPath.append( "e" );
517 0 : break;
518 : default:
519 : // See EscherPropertyContainer::CreateCustomShapeProperties, by default nSeg is simply the number of points.
520 0 : for (int i = 0; i < nSeg; ++i)
521 : {
522 0 : sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nPointSize);
523 0 : sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nPointSize);
524 0 : if (nX >= 0 && nY >= 0 )
525 0 : aPath.append("l").append(nX).append(",").append(nY);
526 : }
527 0 : break;
528 : }
529 : }
530 0 : OString pathString = aPath.makeStringAndClear();
531 0 : if ( !aPath.isEmpty() && pathString != "xe" )
532 0 : m_pShapeAttrList->add( XML_path, pathString );
533 : }
534 : #if OSL_DEBUG_LEVEL > 0
535 : else
536 : fprintf( stderr, "TODO: unhandled shape path, missing either pVertices or pSegmentInfo.\n" );
537 : #endif
538 : }
539 0 : bAlreadyWritten[ ESCHER_Prop_pVertices ] = true;
540 0 : bAlreadyWritten[ ESCHER_Prop_pSegmentInfo ] = true;
541 0 : break;
542 :
543 : case ESCHER_Prop_fillType: // 384
544 : case ESCHER_Prop_fillColor: // 385
545 : case ESCHER_Prop_fillBackColor: // 387
546 : case ESCHER_Prop_fillBlip: // 390
547 : case ESCHER_Prop_fNoFillHitTest: // 447
548 : case ESCHER_Prop_fillOpacity: // 386
549 : {
550 : sal_uInt32 nValue;
551 0 : sax_fastparser::FastAttributeList *pAttrList = m_pSerializer->createAttrList();
552 :
553 0 : if ( rProps.GetOpt( ESCHER_Prop_fillType, nValue ) )
554 : {
555 0 : const char *pFillType = NULL;
556 0 : switch ( nValue )
557 : {
558 0 : case ESCHER_FillSolid: pFillType = "solid"; break;
559 : // TODO case ESCHER_FillPattern: pFillType = ""; break;
560 0 : case ESCHER_FillTexture: pFillType = "tile"; break;
561 : // TODO case ESCHER_FillPicture: pFillType = ""; break;
562 : // TODO case ESCHER_FillShade: pFillType = ""; break;
563 : // TODO case ESCHER_FillShadeCenter: pFillType = ""; break;
564 : // TODO case ESCHER_FillShadeShape: pFillType = ""; break;
565 : // TODO case ESCHER_FillShadeScale: pFillType = ""; break;
566 : // TODO case ESCHER_FillShadeTitle: pFillType = ""; break;
567 : // TODO case ESCHER_FillBackground: pFillType = ""; break;
568 : default:
569 : #if OSL_DEBUG_LEVEL > 0
570 : fprintf( stderr, "TODO: unhandled fill type\n" );
571 : #endif
572 0 : break;
573 : }
574 0 : if ( pFillType )
575 0 : pAttrList->add( XML_type, pFillType );
576 : }
577 0 : else if (!rProps.GetOpt(ESCHER_Prop_fillColor, nValue))
578 0 : pAttrList->add( XML_on, "false" );
579 :
580 0 : if ( rProps.GetOpt( ESCHER_Prop_fillColor, nValue ) )
581 0 : impl_AddColor( m_pShapeAttrList, XML_fillcolor, nValue );
582 :
583 0 : if ( rProps.GetOpt( ESCHER_Prop_fillBackColor, nValue ) )
584 0 : impl_AddColor( pAttrList, XML_color2, nValue );
585 :
586 0 : bool imageData = false;
587 : EscherPropSortStruct aStruct;
588 0 : if ( rProps.GetOpt( ESCHER_Prop_fillBlip, aStruct ) && m_pTextExport)
589 : {
590 0 : SvMemoryStream aStream;
591 0 : int nHeaderSize = 25; // The first bytes are WW8-specific, we're only interested in the PNG
592 0 : aStream.Write(aStruct.pBuf + nHeaderSize, aStruct.nPropSize - nHeaderSize);
593 0 : aStream.Seek(0);
594 0 : Graphic aGraphic;
595 0 : GraphicConverter::Import(aStream, aGraphic);
596 0 : OUString aImageId = m_pTextExport->GetDrawingML().WriteImage( aGraphic );
597 0 : pAttrList->add(FSNS(XML_r, XML_id), OUStringToOString(aImageId, RTL_TEXTENCODING_UTF8));
598 0 : imageData = true;
599 : }
600 :
601 0 : if ( rProps.GetOpt( ESCHER_Prop_fNoFillHitTest, nValue ) )
602 0 : impl_AddBool( pAttrList, FSNS(XML_o, XML_detectmouseclick), nValue != 0 );
603 :
604 0 : if (rProps.GetOpt(ESCHER_Prop_fillOpacity, nValue))
605 : // Partly undo the transformation at the end of EscherPropertyContainer::CreateFillProperties(): VML opacity is 0..1.
606 0 : pAttrList->add(XML_opacity, OString::number(double((nValue * 100) >> 16) / 100));
607 :
608 0 : if (imageData)
609 0 : m_pSerializer->singleElementNS( XML_v, XML_imagedata, XFastAttributeListRef( pAttrList ) );
610 : else
611 0 : m_pSerializer->singleElementNS( XML_v, XML_fill, XFastAttributeListRef( pAttrList ) );
612 : }
613 0 : bAlreadyWritten[ ESCHER_Prop_fillType ] = true;
614 0 : bAlreadyWritten[ ESCHER_Prop_fillColor ] = true;
615 0 : bAlreadyWritten[ ESCHER_Prop_fillBackColor ] = true;
616 0 : bAlreadyWritten[ ESCHER_Prop_fillBlip ] = true;
617 0 : bAlreadyWritten[ ESCHER_Prop_fNoFillHitTest ] = true;
618 0 : bAlreadyWritten[ ESCHER_Prop_fillOpacity ] = true;
619 0 : break;
620 :
621 : case ESCHER_Prop_lineColor: // 448
622 : case ESCHER_Prop_lineWidth: // 459
623 : case ESCHER_Prop_lineDashing: // 462
624 : case ESCHER_Prop_lineStartArrowhead: // 464
625 : case ESCHER_Prop_lineEndArrowhead: // 465
626 : case ESCHER_Prop_lineStartArrowWidth: // 466
627 : case ESCHER_Prop_lineStartArrowLength: // 467
628 : case ESCHER_Prop_lineEndArrowWidth: // 468
629 : case ESCHER_Prop_lineEndArrowLength: // 469
630 : case ESCHER_Prop_lineJoinStyle: // 470
631 : case ESCHER_Prop_lineEndCapStyle: // 471
632 : {
633 : sal_uInt32 nValue;
634 0 : sax_fastparser::FastAttributeList *pAttrList = m_pSerializer->createAttrList();
635 :
636 0 : if ( rProps.GetOpt( ESCHER_Prop_lineColor, nValue ) )
637 0 : impl_AddColor( pAttrList, XML_color, nValue );
638 :
639 0 : if ( rProps.GetOpt( ESCHER_Prop_lineWidth, nValue ) )
640 0 : impl_AddInt( pAttrList, XML_weight, nValue );
641 :
642 0 : if ( rProps.GetOpt( ESCHER_Prop_lineDashing, nValue ) )
643 : {
644 0 : const char *pDashStyle = NULL;
645 0 : switch ( nValue )
646 : {
647 0 : case ESCHER_LineSolid: pDashStyle = "solid"; break;
648 0 : case ESCHER_LineDashSys: pDashStyle = "shortdash"; break;
649 0 : case ESCHER_LineDotSys: pDashStyle = "shortdot"; break;
650 0 : case ESCHER_LineDashDotSys: pDashStyle = "shortdashdot"; break;
651 0 : case ESCHER_LineDashDotDotSys: pDashStyle = "shortdashdotdot"; break;
652 0 : case ESCHER_LineDotGEL: pDashStyle = "dot"; break;
653 0 : case ESCHER_LineDashGEL: pDashStyle = "dash"; break;
654 0 : case ESCHER_LineLongDashGEL: pDashStyle = "longdash"; break;
655 0 : case ESCHER_LineDashDotGEL: pDashStyle = "dashdot"; break;
656 0 : case ESCHER_LineLongDashDotGEL: pDashStyle = "longdashdot"; break;
657 0 : case ESCHER_LineLongDashDotDotGEL: pDashStyle = "longdashdotdot"; break;
658 : }
659 0 : if ( pDashStyle )
660 0 : pAttrList->add( XML_dashstyle, pDashStyle );
661 : }
662 :
663 0 : if ( rProps.GetOpt( ESCHER_Prop_lineStartArrowhead, nValue ) )
664 0 : impl_AddArrowHead( pAttrList, XML_startarrow, nValue );
665 :
666 0 : if ( rProps.GetOpt( ESCHER_Prop_lineEndArrowhead, nValue ) )
667 0 : impl_AddArrowHead( pAttrList, XML_endarrow, nValue );
668 :
669 0 : if ( rProps.GetOpt( ESCHER_Prop_lineStartArrowWidth, nValue ) )
670 0 : impl_AddArrowWidth( pAttrList, XML_startarrowwidth, nValue );
671 :
672 0 : if ( rProps.GetOpt( ESCHER_Prop_lineStartArrowLength, nValue ) )
673 0 : impl_AddArrowLength( pAttrList, XML_startarrowlength, nValue );
674 :
675 0 : if ( rProps.GetOpt( ESCHER_Prop_lineEndArrowWidth, nValue ) )
676 0 : impl_AddArrowWidth( pAttrList, XML_endarrowwidth, nValue );
677 :
678 0 : if ( rProps.GetOpt( ESCHER_Prop_lineEndArrowLength, nValue ) )
679 0 : impl_AddArrowLength( pAttrList, XML_endarrowlength, nValue );
680 :
681 0 : if ( rProps.GetOpt( ESCHER_Prop_lineJoinStyle, nValue ) )
682 : {
683 0 : const char *pJoinStyle = NULL;
684 0 : switch ( nValue )
685 : {
686 0 : case ESCHER_LineJoinBevel: pJoinStyle = "bevel"; break;
687 0 : case ESCHER_LineJoinMiter: pJoinStyle = "miter"; break;
688 0 : case ESCHER_LineJoinRound: pJoinStyle = "round"; break;
689 : }
690 0 : if ( pJoinStyle )
691 0 : pAttrList->add( XML_joinstyle, pJoinStyle );
692 : }
693 :
694 0 : if ( rProps.GetOpt( ESCHER_Prop_lineEndCapStyle, nValue ) )
695 : {
696 0 : const char *pEndCap = NULL;
697 0 : switch ( nValue )
698 : {
699 0 : case ESCHER_LineEndCapRound: pEndCap = "round"; break;
700 0 : case ESCHER_LineEndCapSquare: pEndCap = "square"; break;
701 0 : case ESCHER_LineEndCapFlat: pEndCap = "flat"; break;
702 : }
703 0 : if ( pEndCap )
704 0 : pAttrList->add( XML_endcap, pEndCap );
705 : }
706 :
707 0 : m_pSerializer->singleElementNS( XML_v, XML_stroke, XFastAttributeListRef( pAttrList ) );
708 : }
709 0 : bAlreadyWritten[ ESCHER_Prop_lineColor ] = true;
710 0 : bAlreadyWritten[ ESCHER_Prop_lineWidth ] = true;
711 0 : bAlreadyWritten[ ESCHER_Prop_lineDashing ] = true;
712 0 : bAlreadyWritten[ ESCHER_Prop_lineStartArrowhead ] = true;
713 0 : bAlreadyWritten[ ESCHER_Prop_lineEndArrowhead ] = true;
714 0 : bAlreadyWritten[ ESCHER_Prop_lineStartArrowWidth ] = true;
715 0 : bAlreadyWritten[ ESCHER_Prop_lineStartArrowLength ] = true;
716 0 : bAlreadyWritten[ ESCHER_Prop_lineEndArrowWidth ] = true;
717 0 : bAlreadyWritten[ ESCHER_Prop_lineEndArrowLength ] = true;
718 0 : bAlreadyWritten[ ESCHER_Prop_lineJoinStyle ] = true;
719 0 : bAlreadyWritten[ ESCHER_Prop_lineEndCapStyle ] = true;
720 0 : break;
721 :
722 : case ESCHER_Prop_fHidden:
723 0 : if ( !it->nPropValue )
724 0 : m_pShapeStyle->append( ";visibility:hidden" );
725 0 : break;
726 : case ESCHER_Prop_shadowColor:
727 : case ESCHER_Prop_fshadowObscured:
728 : {
729 0 : sal_uInt32 nValue = 0;
730 0 : bool bShadow = false;
731 0 : bool bObscured = false;
732 0 : if ( rProps.GetOpt( ESCHER_Prop_fshadowObscured, nValue ) )
733 : {
734 0 : bShadow = (( nValue & 0x20002 ) == 0x20002 );
735 0 : bObscured = (( nValue & 0x10001 ) == 0x10001 );
736 : }
737 0 : if ( bShadow )
738 : {
739 0 : sax_fastparser::FastAttributeList *pAttrList = m_pSerializer->createAttrList();
740 0 : impl_AddBool( pAttrList, XML_on, bShadow );
741 0 : impl_AddBool( pAttrList, XML_obscured, bObscured );
742 :
743 0 : if ( rProps.GetOpt( ESCHER_Prop_shadowColor, nValue ) )
744 0 : impl_AddColor( pAttrList, XML_color, nValue );
745 :
746 0 : m_pSerializer->singleElementNS( XML_v, XML_shadow, XFastAttributeListRef( pAttrList ) );
747 0 : bAlreadyWritten[ ESCHER_Prop_fshadowObscured ] = true;
748 0 : bAlreadyWritten[ ESCHER_Prop_shadowColor ] = true;
749 : }
750 : }
751 0 : break;
752 : case ESCHER_Prop_gtextUNICODE:
753 : case ESCHER_Prop_gtextFont:
754 : {
755 : EscherPropSortStruct aUnicode;
756 0 : if (rProps.GetOpt(ESCHER_Prop_gtextUNICODE, aUnicode))
757 : {
758 0 : SvMemoryStream aStream;
759 0 : aStream.Write(it->pBuf, it->nPropSize);
760 0 : aStream.Seek(0);
761 0 : OUString aTextPathString = SvxMSDffManager::MSDFFReadZString(aStream, it->nPropSize, true);
762 0 : aStream.Seek(0);
763 :
764 : m_pSerializer->singleElementNS( XML_v, XML_path,
765 : XML_textpathok, "t",
766 0 : FSEND );
767 :
768 0 : sax_fastparser::FastAttributeList* pAttrList = m_pSerializer->createAttrList();
769 0 : pAttrList->add(XML_on, "t");
770 0 : pAttrList->add(XML_fitshape, "t");
771 0 : pAttrList->add(XML_string, OUStringToOString(aTextPathString, RTL_TEXTENCODING_UTF8));
772 : EscherPropSortStruct aFont;
773 0 : OUString aStyle;
774 0 : if (rProps.GetOpt(ESCHER_Prop_gtextFont, aFont))
775 : {
776 0 : aStream.Write(aFont.pBuf, aFont.nPropSize);
777 0 : aStream.Seek(0);
778 0 : OUString aTextPathFont = SvxMSDffManager::MSDFFReadZString(aStream, aFont.nPropSize, true);
779 0 : aStyle += "font-family:\"" + aTextPathFont + "\"";
780 : }
781 0 : if (!aStyle.isEmpty())
782 0 : pAttrList->add(XML_style, OUStringToOString(aStyle, RTL_TEXTENCODING_UTF8));
783 0 : m_pSerializer->singleElementNS(XML_v, XML_textpath, XFastAttributeListRef(pAttrList));
784 : }
785 :
786 0 : bAlreadyWritten[ESCHER_Prop_gtextUNICODE] = true;
787 0 : bAlreadyWritten[ESCHER_Prop_gtextFont] = true;
788 : }
789 0 : break;
790 : case ESCHER_Prop_Rotation:
791 : {
792 : // The higher half of the variable contains the angle.
793 0 : m_pShapeStyle->append(";rotation:").append(double(it->nPropValue >> 16));
794 0 : bAlreadyWritten[ESCHER_Prop_Rotation] = true;
795 : }
796 0 : break;
797 : case ESCHER_Prop_fNoLineDrawDash:
798 : {
799 : // See DffPropertyReader::ApplyLineAttributes().
800 0 : impl_AddBool( m_pShapeAttrList, XML_stroked, (it->nPropValue & 8) != 0 );
801 0 : bAlreadyWritten[ESCHER_Prop_fNoLineDrawDash] = true;
802 : }
803 0 : break;
804 : case ESCHER_Prop_wzName:
805 : {
806 0 : SvMemoryStream aStream;
807 0 : aStream.Write(it->pBuf, it->nPropSize);
808 0 : aStream.Seek(0);
809 0 : OUString idStr = SvxMSDffManager::MSDFFReadZString(aStream, it->nPropSize, true);
810 0 : aStream.Seek(0);
811 0 : if (!IsWaterMarkShape(m_pSdrObject->GetName()))
812 0 : m_pShapeAttrList->add(XML_ID, OUStringToOString(idStr, RTL_TEXTENCODING_UTF8));
813 :
814 0 : bAlreadyWritten[ESCHER_Prop_wzName] = true;
815 : }
816 0 : break;
817 : default:
818 : #if OSL_DEBUG_LEVEL > 0
819 : fprintf( stderr, "TODO VMLExport::Commit(), unimplemented id: %d, value: %" SAL_PRIuUINT32 ", data: [%" SAL_PRIuUINT32 ", %p]\n",
820 : nId, it->nPropValue, it->nPropSize, it->pBuf );
821 : if ( it->nPropSize )
822 : {
823 : const sal_uInt8 *pIt = it->pBuf;
824 : fprintf( stderr, " ( " );
825 : for ( int nCount = it->nPropSize; nCount; --nCount )
826 : {
827 : fprintf( stderr, "%02x ", *pIt );
828 : ++pIt;
829 : }
830 : fprintf( stderr, ")\n" );
831 : }
832 : #endif
833 0 : break;
834 : }
835 : }
836 :
837 0 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_POSTPONE );
838 : }
839 :
840 0 : OString VMLExport::ShapeIdString( sal_uInt32 nId )
841 : {
842 0 : return OStringBuffer( 20 ).append( "shape_" ).append( sal_Int64( nId ) ).makeStringAndClear();
843 : }
844 :
845 0 : void VMLExport::AddFlipXY( )
846 : {
847 0 : const sal_uInt32 nFlipHandV = SHAPEFLAG_FLIPH + SHAPEFLAG_FLIPV;
848 0 : switch ( m_nShapeFlags & nFlipHandV )
849 : {
850 0 : case SHAPEFLAG_FLIPH: m_pShapeStyle->append( ";flip:x" ); break;
851 0 : case SHAPEFLAG_FLIPV: m_pShapeStyle->append( ";flip:y" ); break;
852 0 : case (nFlipHandV): m_pShapeStyle->append( ";flip:xy" ); break;
853 : }
854 0 : }
855 :
856 0 : void VMLExport::AddLineDimensions( const Rectangle& rRectangle )
857 : {
858 : // style
859 0 : if ( !m_pShapeStyle->isEmpty() )
860 0 : m_pShapeStyle->append( ";" );
861 :
862 0 : m_pShapeStyle->append( "position:absolute" );
863 :
864 0 : AddFlipXY();
865 :
866 : // the actual dimensions
867 0 : OString aLeft, aTop, aRight, aBottom;
868 :
869 0 : if ( mnGroupLevel == 1 )
870 : {
871 0 : const OString aPt( "pt" );
872 0 : aLeft = OString::number( double( rRectangle.Left() ) / 20 ) + aPt;
873 0 : aTop = OString::number( double( rRectangle.Top() ) / 20 ) + aPt;
874 0 : aRight = OString::number( double( rRectangle.Right() ) / 20 ) + aPt;
875 0 : aBottom = OString::number( double( rRectangle.Bottom() ) / 20 ) + aPt;
876 : }
877 : else
878 : {
879 0 : aLeft = OString::number( rRectangle.Left() );
880 0 : aTop = OString::number( rRectangle.Top() );
881 0 : aRight = OString::number( rRectangle.Right() );
882 0 : aBottom = OString::number( rRectangle.Bottom() );
883 : }
884 :
885 : m_pShapeAttrList->add( XML_from,
886 0 : OStringBuffer( 20 ).append( aLeft )
887 0 : .append( "," ).append( aTop )
888 0 : .makeStringAndClear() );
889 :
890 : m_pShapeAttrList->add( XML_to,
891 0 : OStringBuffer( 20 ).append( aRight )
892 0 : .append( "," ).append( aBottom )
893 0 : .makeStringAndClear() );
894 0 : }
895 :
896 0 : void VMLExport::AddRectangleDimensions( OStringBuffer& rBuffer, const Rectangle& rRectangle, bool rbAbsolutePos)
897 : {
898 0 : if ( !rBuffer.isEmpty() )
899 0 : rBuffer.append( ";" );
900 :
901 0 : if (rbAbsolutePos)
902 : {
903 0 : rBuffer.append( "position:absolute;" );
904 : }
905 :
906 0 : if ( mnGroupLevel == 1 )
907 : {
908 0 : rBuffer.append( "margin-left:" ).append( double( rRectangle.Left() ) / 20 )
909 0 : .append( "pt;margin-top:" ).append( double( rRectangle.Top() ) / 20 )
910 0 : .append( "pt;width:" ).append( double( rRectangle.Right() - rRectangle.Left() ) / 20 )
911 0 : .append( "pt;height:" ).append( double( rRectangle.Bottom() - rRectangle.Top() ) / 20 )
912 0 : .append( "pt" );
913 : }
914 : else
915 : {
916 0 : rBuffer.append( "left:" ).append( rRectangle.Left() )
917 0 : .append( ";top:" ).append( rRectangle.Top() )
918 0 : .append( ";width:" ).append( rRectangle.Right() - rRectangle.Left() )
919 0 : .append( ";height:" ).append( rRectangle.Bottom() - rRectangle.Top() );
920 : }
921 :
922 0 : AddFlipXY();
923 0 : }
924 :
925 0 : void VMLExport::AddShapeAttribute( sal_Int32 nAttribute, const OString& rValue )
926 : {
927 0 : m_pShapeAttrList->add( nAttribute, rValue );
928 0 : }
929 :
930 : extern const char* pShapeTypes[];
931 :
932 0 : sal_Int32 VMLExport::StartShape()
933 : {
934 0 : if ( m_nShapeType == ESCHER_ShpInst_Nil )
935 0 : return -1;
936 :
937 : // some of the shapes have their own name ;-)
938 0 : sal_Int32 nShapeElement = -1;
939 0 : bool bReferToShapeType = false;
940 0 : switch ( m_nShapeType )
941 : {
942 0 : case ESCHER_ShpInst_NotPrimitive: nShapeElement = XML_shape; break;
943 0 : case ESCHER_ShpInst_Rectangle: nShapeElement = XML_rect; break;
944 0 : case ESCHER_ShpInst_RoundRectangle: nShapeElement = XML_roundrect; break;
945 0 : case ESCHER_ShpInst_Ellipse: nShapeElement = XML_oval; break;
946 0 : case ESCHER_ShpInst_Arc: nShapeElement = XML_arc; break;
947 0 : case ESCHER_ShpInst_Line: nShapeElement = XML_line; break;
948 : default:
949 0 : if ( m_nShapeType < ESCHER_ShpInst_COUNT )
950 : {
951 0 : nShapeElement = XML_shape;
952 :
953 : // a predefined shape?
954 0 : const char* pShapeType = pShapeTypes[ m_nShapeType ];
955 0 : if ( pShapeType )
956 : {
957 0 : bReferToShapeType = true;
958 0 : if ( !m_pShapeTypeWritten[ m_nShapeType ] )
959 : {
960 0 : m_pSerializer->write( pShapeType );
961 0 : m_pShapeTypeWritten[ m_nShapeType ] = true;
962 : }
963 : }
964 : else
965 : {
966 : // rectangle is probably the best fallback...
967 0 : nShapeElement = XML_rect;
968 : }
969 : }
970 0 : break;
971 : }
972 :
973 : // anchoring
974 0 : switch (m_eHOri)
975 : {
976 : case text::HoriOrientation::LEFT:
977 0 : m_pShapeStyle->append(";mso-position-horizontal:left");
978 0 : break;
979 : case text::HoriOrientation::CENTER:
980 0 : m_pShapeStyle->append(";mso-position-horizontal:center");
981 0 : break;
982 : case text::HoriOrientation::RIGHT:
983 0 : m_pShapeStyle->append(";mso-position-horizontal:right");
984 0 : break;
985 : case text::HoriOrientation::INSIDE:
986 0 : m_pShapeStyle->append(";mso-position-horizontal:inside");
987 0 : break;
988 : case text::HoriOrientation::OUTSIDE:
989 0 : m_pShapeStyle->append(";mso-position-horizontal:outside");
990 0 : break;
991 : default:
992 : case text::HoriOrientation::NONE:
993 0 : break;
994 : }
995 0 : switch (m_eHRel)
996 : {
997 : case text::RelOrientation::PAGE_PRINT_AREA:
998 0 : m_pShapeStyle->append(";mso-position-horizontal-relative:margin");
999 0 : break;
1000 : case text::RelOrientation::PAGE_FRAME:
1001 : case text::RelOrientation::PAGE_LEFT:
1002 : case text::RelOrientation::PAGE_RIGHT:
1003 0 : m_pShapeStyle->append(";mso-position-horizontal-relative:page");
1004 0 : break;
1005 : case text::RelOrientation::CHAR:
1006 0 : m_pShapeStyle->append(";mso-position-horizontal-relative:char");
1007 0 : break;
1008 : default:
1009 0 : break;
1010 : }
1011 :
1012 0 : switch (m_eVOri)
1013 : {
1014 : case text::VertOrientation::TOP:
1015 : case text::VertOrientation::LINE_TOP:
1016 : case text::VertOrientation::CHAR_TOP:
1017 0 : m_pShapeStyle->append(";mso-position-vertical:top");
1018 0 : break;
1019 : case text::VertOrientation::CENTER:
1020 : case text::VertOrientation::LINE_CENTER:
1021 0 : m_pShapeStyle->append(";mso-position-vertical:center");
1022 0 : break;
1023 : case text::VertOrientation::BOTTOM:
1024 : case text::VertOrientation::LINE_BOTTOM:
1025 : case text::VertOrientation::CHAR_BOTTOM:
1026 0 : m_pShapeStyle->append(";mso-position-vertical:bottom");
1027 0 : break;
1028 : default:
1029 : case text::VertOrientation::NONE:
1030 0 : break;
1031 : }
1032 0 : switch (m_eVRel)
1033 : {
1034 : case text::RelOrientation::PAGE_PRINT_AREA:
1035 0 : m_pShapeStyle->append(";mso-position-vertical-relative:margin");
1036 0 : break;
1037 : case text::RelOrientation::PAGE_FRAME:
1038 0 : m_pShapeStyle->append(";mso-position-vertical-relative:page");
1039 0 : break;
1040 : default:
1041 0 : break;
1042 : }
1043 :
1044 : // add style
1045 0 : m_pShapeAttrList->add( XML_style, m_pShapeStyle->makeStringAndClear() );
1046 :
1047 0 : if ( nShapeElement >= 0 && !m_pShapeAttrList->hasAttribute( XML_type ) )
1048 : {
1049 0 : if ( bReferToShapeType )
1050 : {
1051 : m_pShapeAttrList->add( XML_type, OStringBuffer( 20 )
1052 0 : .append( "shapetype_" ).append( sal_Int32( m_nShapeType ) )
1053 0 : .makeStringAndClear() );
1054 : }
1055 :
1056 : // start of the shape
1057 0 : m_pSerializer->startElementNS( XML_v, nShapeElement, XFastAttributeListRef( m_pShapeAttrList ) );
1058 : }
1059 : else
1060 : {
1061 : // start of the shape
1062 0 : m_pSerializer->startElementNS( XML_v, nShapeElement, XFastAttributeListRef( m_pShapeAttrList ) );
1063 : }
1064 :
1065 : // now check if we have some text and we have a text exporter registered
1066 0 : const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, m_pSdrObject);
1067 0 : if (pTxtObj && m_pTextExport && m_nShapeType != ESCHER_ShpInst_TextPlainText)
1068 : {
1069 0 : const OutlinerParaObject* pParaObj = 0;
1070 0 : bool bOwnParaObj = false;
1071 :
1072 : /*
1073 : #i13885#
1074 : When the object is actively being edited, that text is not set into
1075 : the objects normal text object, but lives in a separate object.
1076 : */
1077 0 : if (pTxtObj->IsTextEditActive())
1078 : {
1079 0 : pParaObj = pTxtObj->GetEditOutlinerParaObject();
1080 0 : bOwnParaObj = true;
1081 : }
1082 : else
1083 : {
1084 0 : pParaObj = pTxtObj->GetOutlinerParaObject();
1085 : }
1086 :
1087 0 : if( pParaObj )
1088 : {
1089 : // this is reached only in case some text is attached to the shape
1090 0 : m_pSerializer->startElementNS(XML_v, XML_textbox, FSEND);
1091 0 : m_pTextExport->WriteOutliner(*pParaObj);
1092 0 : m_pSerializer->endElementNS(XML_v, XML_textbox);
1093 0 : if( bOwnParaObj )
1094 0 : delete pParaObj;
1095 : }
1096 : }
1097 :
1098 0 : return nShapeElement;
1099 : }
1100 :
1101 0 : void VMLExport::EndShape( sal_Int32 nShapeElement )
1102 : {
1103 0 : if ( nShapeElement >= 0 )
1104 : {
1105 : // end of the shape
1106 0 : m_pSerializer->endElementNS( XML_v, nShapeElement );
1107 : }
1108 0 : }
1109 :
1110 0 : sal_uInt32 VMLExport::AddSdrObject( const SdrObject& rObj, sal_Int16 eHOri, sal_Int16 eVOri, sal_Int16 eHRel, sal_Int16 eVRel, const Point* pNdTopLeft, const bool bOOxmlExport )
1111 : {
1112 0 : m_pSdrObject = &rObj;
1113 0 : m_eHOri = eHOri;
1114 0 : m_eVOri = eVOri;
1115 0 : m_eHRel = eHRel;
1116 0 : m_eVRel = eVRel;
1117 0 : m_pNdTopLeft = pNdTopLeft;
1118 0 : return EscherEx::AddSdrObject(rObj, bOOxmlExport);
1119 0 : }
1120 :
1121 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|