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 "rtfsdrexport.hxx"
21 : #include "rtfattributeoutput.hxx"
22 : #include "rtfexportfilter.hxx"
23 :
24 : #include <svtools/rtfkeywd.hxx>
25 : #include <filter/msfilter/rtfutil.hxx>
26 : #include <editeng/editobj.hxx>
27 : #include <svx/svdotext.hxx>
28 : #include <svx/unoapi.hxx>
29 : #include <vcl/cvtgrf.hxx>
30 :
31 : #include <algorithm>
32 :
33 : using namespace sw::util;
34 : using namespace css;
35 :
36 56 : RtfSdrExport::RtfSdrExport( RtfExport &rExport )
37 56 : : EscherEx( EscherExGlobalRef( new EscherExGlobal ), 0 ),
38 : m_rExport( rExport ),
39 56 : m_rAttrOutput( (RtfAttributeOutput&)m_rExport.AttrOutput() ),
40 : m_pSdrObject( NULL ),
41 : m_nShapeType( ESCHER_ShpInst_Nil ),
42 : m_nShapeFlags ( 0 ) ,
43 56 : m_pShapeStyle( new OStringBuffer( 200 ) ),
44 224 : m_pShapeTypeWritten( new bool[ ESCHER_ShpInst_COUNT ] )
45 : {
46 56 : mnGroupLevel = 1;
47 56 : memset( m_pShapeTypeWritten, 0, ESCHER_ShpInst_COUNT * sizeof( bool ) );
48 56 : }
49 :
50 168 : RtfSdrExport::~RtfSdrExport()
51 : {
52 56 : delete mpOutStrm, mpOutStrm = NULL;
53 56 : delete m_pShapeStyle, m_pShapeStyle = NULL;
54 56 : delete[] m_pShapeTypeWritten, m_pShapeTypeWritten = NULL;
55 112 : }
56 :
57 63 : void RtfSdrExport::OpenContainer( sal_uInt16 nEscherContainer, int nRecInstance )
58 : {
59 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
60 :
61 63 : EscherEx::OpenContainer( nEscherContainer, nRecInstance );
62 :
63 63 : if ( nEscherContainer == ESCHER_SpContainer )
64 : {
65 63 : m_nShapeType = ESCHER_ShpInst_Nil;
66 63 : if ( !m_pShapeStyle->isEmpty() )
67 0 : m_pShapeStyle->makeStringAndClear();
68 63 : m_pShapeStyle->ensureCapacity( 200 );
69 63 : m_aShapeProps.clear();
70 : }
71 63 : }
72 :
73 63 : void RtfSdrExport::CloseContainer()
74 : {
75 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
76 :
77 63 : if ( mRecTypes.back() == ESCHER_SpContainer )
78 : {
79 : // write the shape now when we have all the info
80 63 : sal_Int32 nShapeElement = StartShape();
81 63 : EndShape( nShapeElement );
82 :
83 : // cleanup
84 63 : m_nShapeType = ESCHER_ShpInst_Nil;
85 : }
86 :
87 63 : EscherEx::CloseContainer();
88 63 : }
89 :
90 2 : sal_uInt32 RtfSdrExport::EnterGroup( const OUString& /*rShapeName*/, const Rectangle* /*pRect*/ )
91 : {
92 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
93 :
94 2 : return GenerateShapeId();
95 : }
96 :
97 2 : void RtfSdrExport::LeaveGroup()
98 : {
99 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
100 :
101 : /* noop */
102 2 : }
103 :
104 63 : void RtfSdrExport::AddShape( sal_uInt32 nShapeType, sal_uInt32 nShapeFlags, sal_uInt32 /*nShapeId*/ )
105 : {
106 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
107 :
108 63 : m_nShapeType = nShapeType;
109 63 : m_nShapeFlags = nShapeFlags;
110 63 : }
111 :
112 22 : inline sal_uInt16 impl_GetUInt16( const sal_uInt8* &pVal )
113 : {
114 22 : sal_uInt16 nRet = *pVal++;
115 22 : nRet += ( *pVal++ ) << 8;
116 22 : return nRet;
117 : }
118 :
119 96 : inline sal_Int32 impl_GetPointComponent( const sal_uInt8* &pVal, sal_Size& rVerticesPos, sal_uInt16 nPointSize )
120 : {
121 96 : sal_Int32 nRet = 0;
122 96 : if ( ( nPointSize == 0xfff0 ) || ( nPointSize == 4 ) )
123 : {
124 0 : sal_uInt16 nUnsigned = *pVal++;
125 0 : nUnsigned += ( *pVal++ ) << 8;
126 0 : rVerticesPos += 2;
127 :
128 0 : nRet = sal_Int16( nUnsigned );
129 : }
130 96 : else if ( nPointSize == 8 )
131 : {
132 96 : sal_uInt32 nUnsigned = *pVal++;
133 96 : nUnsigned += ( *pVal++ ) << 8;
134 96 : nUnsigned += ( *pVal++ ) << 16;
135 96 : nUnsigned += ( *pVal++ ) << 24;
136 96 : rVerticesPos += 4;
137 :
138 96 : nRet = nUnsigned;
139 : }
140 :
141 96 : return nRet;
142 : }
143 :
144 63 : void RtfSdrExport::Commit( EscherPropertyContainer& rProps, const Rectangle& rRect )
145 : {
146 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
147 :
148 63 : if ( m_nShapeType == ESCHER_ShpInst_Nil )
149 63 : return;
150 :
151 63 : if ( m_nShapeType == ESCHER_ShpInst_Line )
152 0 : AddLineDimensions( rRect );
153 : else
154 63 : AddRectangleDimensions( *m_pShapeStyle, rRect );
155 :
156 : // properties
157 63 : const EscherProperties &rOpts = rProps.GetOpts();
158 1008 : for ( EscherProperties::const_iterator it = rOpts.begin(); it != rOpts.end(); ++it )
159 : {
160 945 : sal_uInt16 nId = ( it->nPropId & 0x0FFF );
161 :
162 945 : switch ( nId )
163 : {
164 : case ESCHER_Prop_WrapText:
165 : {
166 36 : int nWrapType = 0;
167 36 : switch ( it->nPropValue )
168 : {
169 13 : case ESCHER_WrapSquare: nWrapType = 2; break;
170 0 : case ESCHER_WrapByPoints: nWrapType = 4; break;
171 23 : case ESCHER_WrapNone: nWrapType = 3; break;
172 0 : case ESCHER_WrapTopBottom: nWrapType = 1; break;
173 0 : case ESCHER_WrapThrough: nWrapType = 5; break;
174 : }
175 36 : if ( nWrapType )
176 36 : m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPWR).append((sal_Int32)nWrapType);
177 : }
178 36 : break;
179 : case ESCHER_Prop_fillColor:
180 17 : m_aShapeProps.insert(std::pair<OString,OString>("fillColor", OString::number(it->nPropValue)));
181 17 : break;
182 : case ESCHER_Prop_fillBackColor:
183 17 : m_aShapeProps.insert(std::pair<OString,OString>("fillBackColor", OString::number(it->nPropValue)));
184 17 : break;
185 : case ESCHER_Prop_AnchorText:
186 36 : m_aShapeProps.insert(std::pair<OString,OString>("anchorText", OString::number(it->nPropValue)));
187 36 : break;
188 : case ESCHER_Prop_fNoFillHitTest:
189 63 : if (it->nPropValue)
190 63 : m_aShapeProps.insert(std::pair<OString,OString>("fNoFillHitTest", OString::number(1)));
191 63 : break;
192 : case ESCHER_Prop_fNoLineDrawDash:
193 : // for some reason the value is set to 0x90000 if lines are switched off
194 63 : if( it->nPropValue == 0x90000 )
195 15 : m_aShapeProps.insert(std::pair<OString,OString>("fLine", OString::number(0)));
196 63 : break;
197 : case ESCHER_Prop_lineColor:
198 63 : m_aShapeProps.insert(std::pair<OString,OString>("lineColor", OString::number(it->nPropValue)));
199 63 : break;
200 : case ESCHER_Prop_lineBackColor:
201 63 : m_aShapeProps.insert(std::pair<OString,OString>("lineBackColor", OString::number(it->nPropValue)));
202 63 : break;
203 : case ESCHER_Prop_lineJoinStyle:
204 63 : m_aShapeProps.insert(std::pair<OString,OString>("lineJoinStyle", OString::number(it->nPropValue)));
205 63 : break;
206 : case ESCHER_Prop_fshadowObscured:
207 63 : if (it->nPropValue)
208 63 : m_aShapeProps.insert(std::pair<OString,OString>("fshadowObscured", "1"));
209 63 : break;
210 : case ESCHER_Prop_geoLeft:
211 : case ESCHER_Prop_geoTop:
212 : {
213 4 : sal_uInt32 nLeft = 0, nTop = 0;
214 :
215 4 : if ( nId == ESCHER_Prop_geoLeft )
216 : {
217 2 : nLeft = it->nPropValue;
218 2 : rProps.GetOpt( ESCHER_Prop_geoTop, nTop );
219 : }
220 : else
221 : {
222 2 : nTop = it->nPropValue;
223 2 : rProps.GetOpt( ESCHER_Prop_geoLeft, nLeft );
224 : }
225 :
226 : m_aShapeProps.insert(std::pair<OString,OString>("geoLeft",
227 4 : OString::number(sal_Int32( nLeft ))));
228 : m_aShapeProps.insert(std::pair<OString,OString>("geoTop",
229 4 : OString::number(sal_Int32( nTop ))));
230 : }
231 4 : break;
232 :
233 : case ESCHER_Prop_geoRight:
234 : case ESCHER_Prop_geoBottom:
235 : {
236 4 : sal_uInt32 nLeft = 0, nRight = 0, nTop = 0, nBottom = 0;
237 4 : rProps.GetOpt( ESCHER_Prop_geoLeft, nLeft );
238 4 : rProps.GetOpt( ESCHER_Prop_geoTop, nTop );
239 :
240 4 : if ( nId == ESCHER_Prop_geoRight )
241 : {
242 2 : nRight = it->nPropValue;
243 2 : rProps.GetOpt( ESCHER_Prop_geoBottom, nBottom );
244 : }
245 : else
246 : {
247 2 : nBottom = it->nPropValue;
248 2 : rProps.GetOpt( ESCHER_Prop_geoRight, nRight );
249 : }
250 :
251 : m_aShapeProps.insert(std::pair<OString,OString>("geoRight",
252 4 : OString::number(sal_Int32( nRight ) - sal_Int32( nLeft ))));
253 : m_aShapeProps.insert(std::pair<OString,OString>("geoBottom",
254 4 : OString::number(sal_Int32( nBottom ) - sal_Int32( nTop ))));
255 : }
256 4 : break;
257 : case ESCHER_Prop_pVertices:
258 : case ESCHER_Prop_pSegmentInfo:
259 : {
260 : EscherPropSortStruct aVertices;
261 : EscherPropSortStruct aSegments;
262 :
263 8 : if ( rProps.GetOpt( ESCHER_Prop_pVertices, aVertices ) &&
264 4 : rProps.GetOpt( ESCHER_Prop_pSegmentInfo, aSegments ) )
265 : {
266 4 : const sal_uInt8 *pVerticesIt = aVertices.pBuf + 6;
267 4 : sal_Size nVerticesPos = 0;
268 4 : const sal_uInt8 *pSegmentIt = aSegments.pBuf;
269 :
270 4 : OStringBuffer aSegmentInfo( 512 );
271 8 : OStringBuffer aVerticies( 512 );
272 :
273 4 : sal_uInt16 nPointSize = aVertices.pBuf[4] + ( aVertices.pBuf[5] << 8 );
274 :
275 : // number of segments
276 4 : sal_uInt16 nSegments = impl_GetUInt16( pSegmentIt );
277 4 : sal_Int32 nVertices = 0;
278 4 : aSegmentInfo.append("2;").append((sal_Int32)nSegments);
279 4 : pSegmentIt += 4;
280 :
281 22 : for ( ; nSegments; --nSegments )
282 : {
283 18 : sal_uInt16 nSeg = impl_GetUInt16( pSegmentIt );
284 18 : aSegmentInfo.append(';').append((sal_Int32)nSeg);
285 18 : switch ( nSeg )
286 : {
287 : case 0x0001: // lineto
288 : case 0x4000: // moveto
289 : {
290 4 : sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nVerticesPos, nPointSize );
291 4 : sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nVerticesPos, nPointSize );
292 4 : aVerticies.append( ";(" ).append( nX ).append( "," ).append( nY ).append( ")" );
293 4 : nVertices ++;
294 : }
295 4 : break;
296 : case 0x2001: // curveto
297 : {
298 0 : for (int i = 0; i < 3; i++)
299 : {
300 0 : sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nVerticesPos, nPointSize );
301 0 : sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nVerticesPos, nPointSize );
302 0 : aVerticies.append( ";(" ).append( nX ).append( "," ).append( nY ).append( ")" );
303 0 : nVertices ++;
304 : }
305 : }
306 0 : break;
307 : case 0xb300:
308 : case 0xac00:
309 : case 0xaa00: // nofill
310 : case 0xab00: // nostroke
311 : case 0x6001: // close
312 : case 0x8000: // end
313 6 : break;
314 : default:
315 : // See EscherPropertyContainer::CreateCustomShapeProperties, by default nSeg is simply the number of points.
316 52 : for (int i = 0; i < nSeg; ++i)
317 : {
318 50 : if (nVerticesPos >= aVertices.nPropSize)
319 6 : break;
320 44 : sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
321 44 : sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
322 44 : aVerticies.append(";(").append(nX).append(",").append(nY).append(")");
323 44 : ++nVertices;
324 : }
325 8 : break;
326 : }
327 : }
328 :
329 4 : if (!aVerticies.isEmpty() )
330 : {
331 : // We know the number of vertices at the end only, so we have to prepend them here.
332 4 : m_aShapeProps.insert(std::pair<OString,OString>("pVerticies", "8;" + OString::number(nVertices) + aVerticies.makeStringAndClear()));
333 : }
334 4 : if ( !aSegmentInfo.isEmpty() )
335 8 : m_aShapeProps.insert(std::pair<OString,OString>("pSegmentInfo", aSegmentInfo.makeStringAndClear()));
336 : }
337 : else
338 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << ": unhandled shape path, missing either pVertices or pSegmentInfo");
339 : }
340 4 : break;
341 : case ESCHER_Prop_shapePath:
342 : // noop, we use pSegmentInfo instead
343 0 : break;
344 : case ESCHER_Prop_fFillOK:
345 27 : if (!it->nPropValue)
346 0 : m_aShapeProps.insert(std::pair<OString,OString>("fFillOK", "0"));
347 27 : break;
348 : case ESCHER_Prop_dxTextLeft:
349 17 : m_aShapeProps.insert(std::pair<OString,OString>("dxTextLeft", OString::number(it->nPropValue)));
350 17 : break;
351 : case ESCHER_Prop_dyTextTop:
352 17 : m_aShapeProps.insert(std::pair<OString,OString>("dyTextTop", OString::number(it->nPropValue)));
353 17 : break;
354 : case ESCHER_Prop_dxTextRight:
355 17 : m_aShapeProps.insert(std::pair<OString,OString>("dxTextRight", OString::number(it->nPropValue)));
356 17 : break;
357 : case ESCHER_Prop_dyTextBottom:
358 17 : m_aShapeProps.insert(std::pair<OString,OString>("dyTextBottom", OString::number(it->nPropValue)));
359 17 : break;
360 : case ESCHER_Prop_FitTextToShape:
361 : // Size text to fit shape size: not supported by RTF
362 17 : break;
363 : case ESCHER_Prop_adjustValue:
364 1 : m_aShapeProps.insert(std::pair<OString,OString>("adjustValue", OString::number(it->nPropValue)));
365 1 : break;
366 : case ESCHER_Prop_txflTextFlow:
367 6 : m_aShapeProps.insert(std::pair<OString,OString>("txflTextFlow", OString::number(it->nPropValue)));
368 6 : break;
369 : case ESCHER_Prop_fillType:
370 22 : m_aShapeProps.insert(std::pair<OString,OString>("fillType", OString::number(it->nPropValue)));
371 22 : break;
372 : case ESCHER_Prop_fillOpacity:
373 16 : m_aShapeProps.insert(std::pair<OString,OString>("fillOpacity", OString::number(it->nPropValue)));
374 16 : break;
375 : case ESCHER_Prop_fillBlip:
376 : {
377 4 : OStringBuffer aBuf;
378 4 : aBuf.append('{').append(OOO_STRING_SVTOOLS_RTF_PICT).append(OOO_STRING_SVTOOLS_RTF_PNGBLIP).append(SAL_NEWLINE_STRING);
379 4 : int nHeaderSize = 25; // The first bytes are WW8-specific, we're only interested in the PNG
380 4 : aBuf.append(RtfAttributeOutput::WriteHex(it->pBuf + nHeaderSize, it->nPropSize - nHeaderSize));
381 4 : aBuf.append('}');
382 4 : m_aShapeProps.insert(std::pair<OString,OString>("fillBlip", aBuf.makeStringAndClear()));
383 : }
384 4 : break;
385 : default:
386 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << ": unhandled property: " << nId << " (value: " << it->nPropValue << ")");
387 288 : break;
388 : }
389 63 : }
390 : }
391 :
392 0 : void RtfSdrExport::AddLineDimensions( const Rectangle& rRectangle )
393 : {
394 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
395 :
396 : // We get the position relative to (the current?) character
397 0 : m_aShapeProps.insert(std::pair<OString,OString>("posrelh", "3"));
398 :
399 0 : switch ( m_nShapeFlags & 0xC0 )
400 : {
401 : case 0x40:
402 0 : m_aShapeProps.insert(std::pair<OString,OString>("fFlipV", "1"));
403 0 : break;
404 : case 0x80:
405 0 : m_aShapeProps.insert(std::pair<OString,OString>("fFlipH", "1"));
406 0 : break;
407 : case 0xC0:
408 0 : m_aShapeProps.insert(std::pair<OString,OString>("fFlipV", "1"));
409 0 : m_aShapeProps.insert(std::pair<OString,OString>("fFlipH", "1"));
410 0 : break;
411 : }
412 :
413 : // the actual dimensions
414 0 : m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPLEFT).append(rRectangle.Left());
415 0 : m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPTOP).append(rRectangle.Top());
416 0 : m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPRIGHT).append(rRectangle.Right());
417 0 : m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPBOTTOM).append(rRectangle.Bottom());
418 0 : }
419 :
420 63 : void RtfSdrExport::AddRectangleDimensions( OStringBuffer& rBuffer, const Rectangle& rRectangle )
421 : {
422 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
423 :
424 : // We get the position relative to (the current?) character
425 63 : m_aShapeProps.insert(std::pair<OString,OString>("posrelh", "3"));
426 :
427 63 : rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPLEFT).append(rRectangle.Left());
428 63 : rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPTOP).append(rRectangle.Top());
429 63 : rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPRIGHT).append(rRectangle.Right());
430 63 : rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPBOTTOM).append(rRectangle.Bottom());
431 63 : }
432 :
433 : extern const char* pShapeTypes[];
434 :
435 781 : static void lcl_AppendSP( OStringBuffer& rRunText, const char cName[], const OString& rValue)
436 : {
437 781 : rRunText.append('{').append(OOO_STRING_SVTOOLS_RTF_SP)
438 781 : .append('{').append(OOO_STRING_SVTOOLS_RTF_SN " ").append(cName).append('}')
439 781 : .append('{').append(OOO_STRING_SVTOOLS_RTF_SV " ").append(rValue).append('}')
440 781 : .append('}');
441 781 : }
442 :
443 6 : void RtfSdrExport::impl_writeGraphic()
444 : {
445 : // Get the Graphic object from the Sdr one.
446 6 : uno::Reference<drawing::XShape> xShape = GetXShapeForSdrObject(const_cast<SdrObject*>(m_pSdrObject));
447 6 : uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
448 6 : OUString sGraphicURL;
449 : try
450 : {
451 12 : xPropertySet->getPropertyValue("GraphicURL") >>= sGraphicURL;
452 : }
453 12 : catch (beans::UnknownPropertyException& rException)
454 : {
455 : // ATM groupshapes are not supported, just make sure we don't crash on them.
456 : SAL_WARN("sw.rtf", "failed. Message: " << rException.Message);
457 12 : return;
458 : }
459 0 : OString aURLBS(OUStringToOString(sGraphicURL, RTL_TEXTENCODING_UTF8));
460 0 : const char aURLBegin[] = "vnd.sun.star.GraphicObject:";
461 0 : Graphic aGraphic = GraphicObject(aURLBS.copy(RTL_CONSTASCII_LENGTH(aURLBegin))).GetTransformedGraphic();
462 :
463 : // Export it to a stream.
464 0 : SvMemoryStream aStream;
465 0 : GraphicConverter::Export(aStream, aGraphic, CVT_PNG);
466 0 : aStream.Seek(STREAM_SEEK_TO_END);
467 0 : sal_uInt32 nSize = aStream.Tell();
468 0 : const sal_uInt8* pGraphicAry = (sal_uInt8*)aStream.GetData();
469 :
470 0 : Size aMapped(aGraphic.GetPrefSize());
471 :
472 : // Add it to the properties.
473 0 : RtfStringBuffer aBuf;
474 0 : aBuf->append('{').append(OOO_STRING_SVTOOLS_RTF_PICT).append(OOO_STRING_SVTOOLS_RTF_PNGBLIP);
475 0 : aBuf->append(OOO_STRING_SVTOOLS_RTF_PICW).append(sal_Int32(aMapped.Width()));
476 0 : aBuf->append(OOO_STRING_SVTOOLS_RTF_PICH).append(sal_Int32(aMapped.Height())).append(SAL_NEWLINE_STRING);
477 0 : aBuf->append(RtfAttributeOutput::WriteHex(pGraphicAry, nSize));
478 0 : aBuf->append('}');
479 0 : m_aShapeProps.insert(std::pair<OString,OString>("pib", aBuf.makeStringAndClear()));
480 : }
481 :
482 63 : sal_Int32 RtfSdrExport::StartShape()
483 : {
484 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
485 :
486 63 : if ( m_nShapeType == ESCHER_ShpInst_Nil )
487 0 : return -1;
488 :
489 63 : m_aShapeProps.insert(std::pair<OString,OString>("shapeType", OString::number(m_nShapeType)));
490 63 : if (ESCHER_ShpInst_PictureFrame == m_nShapeType)
491 6 : impl_writeGraphic();
492 :
493 63 : m_rAttrOutput.RunText().append('{').append(OOO_STRING_SVTOOLS_RTF_SHP);
494 63 : m_rAttrOutput.RunText().append('{').append(OOO_STRING_SVTOOLS_RTF_IGNORE).append(OOO_STRING_SVTOOLS_RTF_SHPINST);
495 :
496 63 : m_rAttrOutput.RunText().append(m_pShapeStyle->makeStringAndClear());
497 : // Ignore \shpbxpage, \shpbxmargin, and \shpbxcolumn, in favor of the posrelh property.
498 63 : m_rAttrOutput.RunText().append(OOO_STRING_SVTOOLS_RTF_SHPBXIGNORE);
499 : // Ignore \shpbypage, \shpbymargin, and \shpbycolumn, in favor of the posrelh property.
500 63 : m_rAttrOutput.RunText().append(OOO_STRING_SVTOOLS_RTF_SHPBYIGNORE);
501 :
502 718 : for(std::map<OString,OString>::reverse_iterator i = m_aShapeProps.rbegin(); i != m_aShapeProps.rend(); ++i)
503 655 : lcl_AppendSP(m_rAttrOutput.RunText(), (*i).first.getStr(), (*i).second );
504 :
505 63 : lcl_AppendSP(m_rAttrOutput.RunText(), "wzDescription", msfilter::rtfutil::OutString( m_pSdrObject->GetDescription(), m_rExport.eCurrentEncoding));
506 63 : lcl_AppendSP(m_rAttrOutput.RunText(), "wzName", msfilter::rtfutil::OutString( m_pSdrObject->GetTitle(), m_rExport.eCurrentEncoding));
507 :
508 : // now check if we have some text
509 63 : const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, m_pSdrObject);
510 63 : if (pTxtObj)
511 : {
512 3 : const OutlinerParaObject* pParaObj = 0;
513 3 : bool bOwnParaObj = false;
514 :
515 : /*
516 : #i13885#
517 : When the object is actively being edited, that text is not set into
518 : the objects normal text object, but lives in a separate object.
519 : */
520 3 : if (pTxtObj->IsTextEditActive())
521 : {
522 0 : pParaObj = pTxtObj->GetEditOutlinerParaObject();
523 0 : bOwnParaObj = true;
524 : }
525 : else
526 : {
527 3 : pParaObj = pTxtObj->GetOutlinerParaObject();
528 : }
529 :
530 3 : if( pParaObj )
531 : {
532 : // this is reached only in case some text is attached to the shape
533 2 : WriteOutliner(*pParaObj);
534 2 : if( bOwnParaObj )
535 0 : delete pParaObj;
536 : }
537 : }
538 :
539 63 : return m_nShapeType;
540 : }
541 :
542 2 : void RtfSdrExport::WriteOutliner(const OutlinerParaObject& rParaObj)
543 : {
544 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " start");
545 :
546 2 : const EditTextObject& rEditObj = rParaObj.GetTextObject();
547 2 : MSWord_SdrAttrIter aAttrIter( m_rExport, rEditObj, TXT_HFTXTBOX );
548 :
549 2 : sal_Int32 nPara = rEditObj.GetParagraphCount();
550 :
551 2 : m_rAttrOutput.RunText().append('{').append(OOO_STRING_SVTOOLS_RTF_SHPTXT).append(' ');
552 4 : for (sal_Int32 n = 0; n < nPara; ++n)
553 : {
554 2 : if( n )
555 0 : aAttrIter.NextPara( n );
556 :
557 2 : rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet();
558 :
559 2 : OUString aStr( rEditObj.GetText( n ));
560 2 : sal_Int32 nAktPos = 0;
561 2 : const sal_Int32 nEnd = aStr.getLength();
562 :
563 2 : aAttrIter.OutParaAttr(false);
564 2 : m_rAttrOutput.RunText().append(m_rAttrOutput.Styles().makeStringAndClear());
565 :
566 2 : do {
567 2 : const sal_Int32 nNextAttr = std::min(aAttrIter.WhereNext(), nEnd);
568 2 : rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet();
569 :
570 2 : aAttrIter.OutAttr( nAktPos );
571 2 : m_rAttrOutput.RunText().append('{').append(m_rAttrOutput.Styles().makeStringAndClear()).append(SAL_NEWLINE_STRING);
572 2 : bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
573 2 : if( !bTxtAtr )
574 : {
575 2 : OUString aOut( aStr.copy( nAktPos, nNextAttr - nAktPos ) );
576 2 : m_rAttrOutput.RunText().append( msfilter::rtfutil::OutString( aOut, eChrSet ) );
577 : }
578 :
579 2 : m_rAttrOutput.RunText().append('}');
580 :
581 2 : nAktPos = nNextAttr;
582 2 : eChrSet = eNextChrSet;
583 2 : aAttrIter.NextPos();
584 : }
585 2 : while( nAktPos < nEnd );
586 2 : }
587 2 : m_rAttrOutput.RunText().append(OOO_STRING_SVTOOLS_RTF_PAR).append('}');
588 :
589 2 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " end");
590 2 : }
591 :
592 63 : void RtfSdrExport::EndShape( sal_Int32 nShapeElement )
593 : {
594 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
595 :
596 63 : if ( nShapeElement >= 0 )
597 : {
598 : // end of the shape
599 63 : m_rAttrOutput.RunText().append('}').append('}');
600 : }
601 63 : }
602 :
603 5 : sal_uInt32 RtfSdrExport::AddSdrObject( const SdrObject& rObj )
604 : {
605 5 : m_pSdrObject = &rObj;
606 5 : return EscherEx::AddSdrObject(rObj);
607 : }
608 :
609 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|