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 0 : RtfSdrExport::RtfSdrExport( RtfExport &rExport )
37 0 : : EscherEx( EscherExGlobalRef( new EscherExGlobal ), 0 ),
38 : m_rExport( rExport ),
39 0 : m_rAttrOutput( (RtfAttributeOutput&)m_rExport.AttrOutput() ),
40 : m_pSdrObject( NULL ),
41 : m_nShapeType( ESCHER_ShpInst_Nil ),
42 : m_nShapeFlags ( 0 ) ,
43 0 : m_pShapeStyle( new OStringBuffer( 200 ) ),
44 0 : m_pShapeTypeWritten( new bool[ ESCHER_ShpInst_COUNT ] )
45 : {
46 0 : mnGroupLevel = 1;
47 0 : memset( m_pShapeTypeWritten, 0, ESCHER_ShpInst_COUNT * sizeof( bool ) );
48 0 : }
49 :
50 0 : RtfSdrExport::~RtfSdrExport()
51 : {
52 0 : delete mpOutStrm, mpOutStrm = NULL;
53 0 : delete m_pShapeStyle, m_pShapeStyle = NULL;
54 0 : delete[] m_pShapeTypeWritten, m_pShapeTypeWritten = NULL;
55 0 : }
56 :
57 0 : void RtfSdrExport::OpenContainer( sal_uInt16 nEscherContainer, int nRecInstance )
58 : {
59 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
60 :
61 0 : EscherEx::OpenContainer( nEscherContainer, nRecInstance );
62 :
63 0 : if ( nEscherContainer == ESCHER_SpContainer )
64 : {
65 0 : m_nShapeType = ESCHER_ShpInst_Nil;
66 0 : if ( !m_pShapeStyle->isEmpty() )
67 0 : m_pShapeStyle->makeStringAndClear();
68 0 : m_pShapeStyle->ensureCapacity( 200 );
69 0 : m_aShapeProps.clear();
70 : }
71 0 : }
72 :
73 0 : void RtfSdrExport::CloseContainer()
74 : {
75 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
76 :
77 0 : if ( mRecTypes.back() == ESCHER_SpContainer )
78 : {
79 : // write the shape now when we have all the info
80 0 : sal_Int32 nShapeElement = StartShape();
81 0 : EndShape( nShapeElement );
82 :
83 : // cleanup
84 0 : m_nShapeType = ESCHER_ShpInst_Nil;
85 : }
86 :
87 0 : EscherEx::CloseContainer();
88 0 : }
89 :
90 0 : sal_uInt32 RtfSdrExport::EnterGroup( const OUString& /*rShapeName*/, const Rectangle* /*pRect*/ )
91 : {
92 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
93 :
94 0 : return GenerateShapeId();
95 : }
96 :
97 0 : void RtfSdrExport::LeaveGroup()
98 : {
99 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
100 :
101 : /* noop */
102 0 : }
103 :
104 0 : void RtfSdrExport::AddShape( sal_uInt32 nShapeType, sal_uInt32 nShapeFlags, sal_uInt32 /*nShapeId*/ )
105 : {
106 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
107 :
108 0 : m_nShapeType = nShapeType;
109 0 : m_nShapeFlags = nShapeFlags;
110 0 : }
111 :
112 0 : inline sal_uInt16 impl_GetUInt16( const sal_uInt8* &pVal )
113 : {
114 0 : sal_uInt16 nRet = *pVal++;
115 0 : nRet += ( *pVal++ ) << 8;
116 0 : return nRet;
117 : }
118 :
119 0 : inline sal_Int32 impl_GetPointComponent( const sal_uInt8* &pVal, sal_Size& rVerticesPos, sal_uInt16 nPointSize )
120 : {
121 0 : sal_Int32 nRet = 0;
122 0 : 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 0 : else if ( nPointSize == 8 )
131 : {
132 0 : sal_uInt32 nUnsigned = *pVal++;
133 0 : nUnsigned += ( *pVal++ ) << 8;
134 0 : nUnsigned += ( *pVal++ ) << 16;
135 0 : nUnsigned += ( *pVal++ ) << 24;
136 0 : rVerticesPos += 4;
137 :
138 0 : nRet = nUnsigned;
139 : }
140 :
141 0 : return nRet;
142 : }
143 :
144 0 : void RtfSdrExport::Commit( EscherPropertyContainer& rProps, const Rectangle& rRect )
145 : {
146 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
147 :
148 0 : if ( m_nShapeType == ESCHER_ShpInst_Nil )
149 0 : return;
150 :
151 0 : if ( m_nShapeType == ESCHER_ShpInst_Line )
152 0 : AddLineDimensions( rRect );
153 : else
154 0 : AddRectangleDimensions( *m_pShapeStyle, rRect );
155 :
156 : // properties
157 0 : const EscherProperties &rOpts = rProps.GetOpts();
158 0 : for ( EscherProperties::const_iterator it = rOpts.begin(); it != rOpts.end(); ++it )
159 : {
160 0 : sal_uInt16 nId = ( it->nPropId & 0x0FFF );
161 :
162 0 : switch ( nId )
163 : {
164 : case ESCHER_Prop_WrapText:
165 : {
166 0 : int nWrapType = 0;
167 0 : switch ( it->nPropValue )
168 : {
169 0 : case ESCHER_WrapSquare: nWrapType = 2; break;
170 0 : case ESCHER_WrapByPoints: nWrapType = 4; break;
171 0 : case ESCHER_WrapNone: nWrapType = 3; break;
172 0 : case ESCHER_WrapTopBottom: nWrapType = 1; break;
173 0 : case ESCHER_WrapThrough: nWrapType = 5; break;
174 : }
175 0 : if ( nWrapType )
176 0 : m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPWR).append((sal_Int32)nWrapType);
177 : }
178 0 : break;
179 : case ESCHER_Prop_fillColor:
180 0 : m_aShapeProps.insert(std::pair<OString,OString>("fillColor", OString::number(it->nPropValue)));
181 0 : break;
182 : case ESCHER_Prop_fillBackColor:
183 0 : m_aShapeProps.insert(std::pair<OString,OString>("fillBackColor", OString::number(it->nPropValue)));
184 0 : break;
185 : case ESCHER_Prop_AnchorText:
186 0 : m_aShapeProps.insert(std::pair<OString,OString>("anchorText", OString::number(it->nPropValue)));
187 0 : break;
188 : case ESCHER_Prop_fNoFillHitTest:
189 0 : if (it->nPropValue)
190 0 : m_aShapeProps.insert(std::pair<OString,OString>("fNoFillHitTest", OString::number(1)));
191 0 : break;
192 : case ESCHER_Prop_fNoLineDrawDash:
193 : // for some reason the value is set to 0x90000 if lines are switched off
194 0 : if( it->nPropValue == 0x90000 )
195 0 : m_aShapeProps.insert(std::pair<OString,OString>("fLine", OString::number(0)));
196 0 : break;
197 : case ESCHER_Prop_lineColor:
198 0 : m_aShapeProps.insert(std::pair<OString,OString>("lineColor", OString::number(it->nPropValue)));
199 0 : break;
200 : case ESCHER_Prop_lineBackColor:
201 0 : m_aShapeProps.insert(std::pair<OString,OString>("lineBackColor", OString::number(it->nPropValue)));
202 0 : break;
203 : case ESCHER_Prop_lineJoinStyle:
204 0 : m_aShapeProps.insert(std::pair<OString,OString>("lineJoinStyle", OString::number(it->nPropValue)));
205 0 : break;
206 : case ESCHER_Prop_fshadowObscured:
207 0 : if (it->nPropValue)
208 0 : m_aShapeProps.insert(std::pair<OString,OString>("fshadowObscured", "1"));
209 0 : break;
210 : case ESCHER_Prop_geoLeft:
211 : case ESCHER_Prop_geoTop:
212 : {
213 0 : sal_uInt32 nLeft = 0, nTop = 0;
214 :
215 0 : if ( nId == ESCHER_Prop_geoLeft )
216 : {
217 0 : nLeft = it->nPropValue;
218 0 : rProps.GetOpt( ESCHER_Prop_geoTop, nTop );
219 : }
220 : else
221 : {
222 0 : nTop = it->nPropValue;
223 0 : rProps.GetOpt( ESCHER_Prop_geoLeft, nLeft );
224 : }
225 :
226 : m_aShapeProps.insert(std::pair<OString,OString>("geoLeft",
227 0 : OString::number(sal_Int32( nLeft ))));
228 : m_aShapeProps.insert(std::pair<OString,OString>("geoTop",
229 0 : OString::number(sal_Int32( nTop ))));
230 : }
231 0 : break;
232 :
233 : case ESCHER_Prop_geoRight:
234 : case ESCHER_Prop_geoBottom:
235 : {
236 0 : sal_uInt32 nLeft = 0, nRight = 0, nTop = 0, nBottom = 0;
237 0 : rProps.GetOpt( ESCHER_Prop_geoLeft, nLeft );
238 0 : rProps.GetOpt( ESCHER_Prop_geoTop, nTop );
239 :
240 0 : if ( nId == ESCHER_Prop_geoRight )
241 : {
242 0 : nRight = it->nPropValue;
243 0 : rProps.GetOpt( ESCHER_Prop_geoBottom, nBottom );
244 : }
245 : else
246 : {
247 0 : nBottom = it->nPropValue;
248 0 : rProps.GetOpt( ESCHER_Prop_geoRight, nRight );
249 : }
250 :
251 : m_aShapeProps.insert(std::pair<OString,OString>("geoRight",
252 0 : OString::number(sal_Int32( nRight ) - sal_Int32( nLeft ))));
253 : m_aShapeProps.insert(std::pair<OString,OString>("geoBottom",
254 0 : OString::number(sal_Int32( nBottom ) - sal_Int32( nTop ))));
255 : }
256 0 : break;
257 : case ESCHER_Prop_pVertices:
258 : case ESCHER_Prop_pSegmentInfo:
259 : {
260 : EscherPropSortStruct aVertices;
261 : EscherPropSortStruct aSegments;
262 :
263 0 : if ( rProps.GetOpt( ESCHER_Prop_pVertices, aVertices ) &&
264 0 : rProps.GetOpt( ESCHER_Prop_pSegmentInfo, aSegments ) )
265 : {
266 0 : const sal_uInt8 *pVerticesIt = aVertices.pBuf + 6;
267 0 : sal_Size nVerticesPos = 0;
268 0 : const sal_uInt8 *pSegmentIt = aSegments.pBuf;
269 :
270 0 : OStringBuffer aSegmentInfo( 512 );
271 0 : OStringBuffer aVerticies( 512 );
272 :
273 0 : sal_uInt16 nPointSize = aVertices.pBuf[4] + ( aVertices.pBuf[5] << 8 );
274 :
275 : // number of segments
276 0 : sal_uInt16 nSegments = impl_GetUInt16( pSegmentIt );
277 0 : sal_Int32 nVertices = 0;
278 0 : aSegmentInfo.append("2;").append((sal_Int32)nSegments);
279 0 : pSegmentIt += 4;
280 :
281 0 : for ( ; nSegments; --nSegments )
282 : {
283 0 : sal_uInt16 nSeg = impl_GetUInt16( pSegmentIt );
284 0 : aSegmentInfo.append(';').append((sal_Int32)nSeg);
285 0 : switch ( nSeg )
286 : {
287 : case 0x0001: // lineto
288 : case 0x4000: // moveto
289 : {
290 0 : sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nVerticesPos, nPointSize );
291 0 : sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nVerticesPos, nPointSize );
292 0 : aVerticies.append( ";(" ).append( nX ).append( "," ).append( nY ).append( ")" );
293 0 : nVertices ++;
294 : }
295 0 : 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 0 : break;
314 : default:
315 : // See EscherPropertyContainer::CreateCustomShapeProperties, by default nSeg is simply the number of points.
316 0 : for (int i = 0; i < nSeg; ++i)
317 : {
318 0 : if (nVerticesPos >= aVertices.nPropSize)
319 0 : break;
320 0 : sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
321 0 : sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
322 0 : aVerticies.append(";(").append(nX).append(",").append(nY).append(")");
323 0 : ++nVertices;
324 : }
325 0 : break;
326 : }
327 : }
328 :
329 0 : if (!aVerticies.isEmpty() )
330 : {
331 : // We know the number of vertices at the end only, so we have to prepend them here.
332 0 : m_aShapeProps.insert(std::pair<OString,OString>("pVerticies", "8;" + OString::number(nVertices) + aVerticies.makeStringAndClear()));
333 : }
334 0 : if ( !aSegmentInfo.isEmpty() )
335 0 : 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 0 : break;
341 : case ESCHER_Prop_shapePath:
342 : // noop, we use pSegmentInfo instead
343 0 : break;
344 : case ESCHER_Prop_fFillOK:
345 0 : if (!it->nPropValue)
346 0 : m_aShapeProps.insert(std::pair<OString,OString>("fFillOK", "0"));
347 0 : break;
348 : case ESCHER_Prop_dxTextLeft:
349 0 : m_aShapeProps.insert(std::pair<OString,OString>("dxTextLeft", OString::number(it->nPropValue)));
350 0 : break;
351 : case ESCHER_Prop_dyTextTop:
352 0 : m_aShapeProps.insert(std::pair<OString,OString>("dyTextTop", OString::number(it->nPropValue)));
353 0 : break;
354 : case ESCHER_Prop_dxTextRight:
355 0 : m_aShapeProps.insert(std::pair<OString,OString>("dxTextRight", OString::number(it->nPropValue)));
356 0 : break;
357 : case ESCHER_Prop_dyTextBottom:
358 0 : m_aShapeProps.insert(std::pair<OString,OString>("dyTextBottom", OString::number(it->nPropValue)));
359 0 : break;
360 : case ESCHER_Prop_FitTextToShape:
361 : // Size text to fit shape size: not supported by RTF
362 0 : break;
363 : case ESCHER_Prop_adjustValue:
364 0 : m_aShapeProps.insert(std::pair<OString,OString>("adjustValue", OString::number(it->nPropValue)));
365 0 : break;
366 : case ESCHER_Prop_txflTextFlow:
367 0 : m_aShapeProps.insert(std::pair<OString,OString>("txflTextFlow", OString::number(it->nPropValue)));
368 0 : break;
369 : case ESCHER_Prop_fillType:
370 0 : m_aShapeProps.insert(std::pair<OString,OString>("fillType", OString::number(it->nPropValue)));
371 0 : break;
372 : case ESCHER_Prop_fillOpacity:
373 0 : m_aShapeProps.insert(std::pair<OString,OString>("fillOpacity", OString::number(it->nPropValue)));
374 0 : break;
375 : case ESCHER_Prop_fillBlip:
376 : {
377 0 : OStringBuffer aBuf;
378 0 : aBuf.append('{').append(OOO_STRING_SVTOOLS_RTF_PICT).append(OOO_STRING_SVTOOLS_RTF_PNGBLIP).append(SAL_NEWLINE_STRING);
379 0 : int nHeaderSize = 25; // The first bytes are WW8-specific, we're only interested in the PNG
380 0 : aBuf.append(RtfAttributeOutput::WriteHex(it->pBuf + nHeaderSize, it->nPropSize - nHeaderSize));
381 0 : aBuf.append('}');
382 0 : m_aShapeProps.insert(std::pair<OString,OString>("fillBlip", aBuf.makeStringAndClear()));
383 : }
384 0 : break;
385 : default:
386 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << ": unhandled property: " << nId << " (value: " << it->nPropValue << ")");
387 0 : break;
388 : }
389 0 : }
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 0 : 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 0 : m_aShapeProps.insert(std::pair<OString,OString>("posrelh", "3"));
426 :
427 0 : rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPLEFT).append(rRectangle.Left());
428 0 : rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPTOP).append(rRectangle.Top());
429 0 : rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPRIGHT).append(rRectangle.Right());
430 0 : rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPBOTTOM).append(rRectangle.Bottom());
431 0 : }
432 :
433 : extern const char* pShapeTypes[];
434 :
435 0 : static void lcl_AppendSP( OStringBuffer& rRunText, const char cName[], const OString& rValue)
436 : {
437 0 : rRunText.append('{').append(OOO_STRING_SVTOOLS_RTF_SP)
438 0 : .append('{').append(OOO_STRING_SVTOOLS_RTF_SN " ").append(cName).append('}')
439 0 : .append('{').append(OOO_STRING_SVTOOLS_RTF_SV " ").append(rValue).append('}')
440 0 : .append('}');
441 0 : }
442 :
443 0 : void RtfSdrExport::impl_writeGraphic()
444 : {
445 : // Get the Graphic object from the Sdr one.
446 0 : uno::Reference<drawing::XShape> xShape = GetXShapeForSdrObject(const_cast<SdrObject*>(m_pSdrObject));
447 0 : uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
448 0 : OUString sGraphicURL;
449 : try
450 : {
451 0 : xPropertySet->getPropertyValue("GraphicURL") >>= sGraphicURL;
452 : }
453 0 : 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 0 : 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 0 : sal_Int32 RtfSdrExport::StartShape()
483 : {
484 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
485 :
486 0 : if ( m_nShapeType == ESCHER_ShpInst_Nil )
487 0 : return -1;
488 :
489 0 : m_aShapeProps.insert(std::pair<OString,OString>("shapeType", OString::number(m_nShapeType)));
490 0 : if (ESCHER_ShpInst_PictureFrame == m_nShapeType)
491 0 : impl_writeGraphic();
492 :
493 0 : m_rAttrOutput.RunText().append('{').append(OOO_STRING_SVTOOLS_RTF_SHP);
494 0 : m_rAttrOutput.RunText().append('{').append(OOO_STRING_SVTOOLS_RTF_IGNORE).append(OOO_STRING_SVTOOLS_RTF_SHPINST);
495 :
496 0 : m_rAttrOutput.RunText().append(m_pShapeStyle->makeStringAndClear());
497 : // Ignore \shpbxpage, \shpbxmargin, and \shpbxcolumn, in favor of the posrelh property.
498 0 : m_rAttrOutput.RunText().append(OOO_STRING_SVTOOLS_RTF_SHPBXIGNORE);
499 : // Ignore \shpbypage, \shpbymargin, and \shpbycolumn, in favor of the posrelh property.
500 0 : m_rAttrOutput.RunText().append(OOO_STRING_SVTOOLS_RTF_SHPBYIGNORE);
501 :
502 0 : for(std::map<OString,OString>::reverse_iterator i = m_aShapeProps.rbegin(); i != m_aShapeProps.rend(); ++i)
503 0 : lcl_AppendSP(m_rAttrOutput.RunText(), (*i).first.getStr(), (*i).second );
504 :
505 0 : lcl_AppendSP(m_rAttrOutput.RunText(), "wzDescription", msfilter::rtfutil::OutString( m_pSdrObject->GetDescription(), m_rExport.eCurrentEncoding));
506 0 : 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 0 : const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, m_pSdrObject);
510 0 : if (pTxtObj)
511 : {
512 0 : const OutlinerParaObject* pParaObj = 0;
513 0 : 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 0 : if (pTxtObj->IsTextEditActive())
521 : {
522 0 : pParaObj = pTxtObj->GetEditOutlinerParaObject();
523 0 : bOwnParaObj = true;
524 : }
525 : else
526 : {
527 0 : pParaObj = pTxtObj->GetOutlinerParaObject();
528 : }
529 :
530 0 : if( pParaObj )
531 : {
532 : // this is reached only in case some text is attached to the shape
533 0 : WriteOutliner(*pParaObj);
534 0 : if( bOwnParaObj )
535 0 : delete pParaObj;
536 : }
537 : }
538 :
539 0 : return m_nShapeType;
540 : }
541 :
542 0 : void RtfSdrExport::WriteOutliner(const OutlinerParaObject& rParaObj)
543 : {
544 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " start");
545 :
546 0 : const EditTextObject& rEditObj = rParaObj.GetTextObject();
547 0 : MSWord_SdrAttrIter aAttrIter( m_rExport, rEditObj, TXT_HFTXTBOX );
548 :
549 0 : sal_Int32 nPara = rEditObj.GetParagraphCount();
550 :
551 0 : m_rAttrOutput.RunText().append('{').append(OOO_STRING_SVTOOLS_RTF_SHPTXT).append(' ');
552 0 : for (sal_Int32 n = 0; n < nPara; ++n)
553 : {
554 0 : if( n )
555 0 : aAttrIter.NextPara( n );
556 :
557 0 : rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet();
558 :
559 0 : OUString aStr( rEditObj.GetText( n ));
560 0 : sal_Int32 nAktPos = 0;
561 0 : const sal_Int32 nEnd = aStr.getLength();
562 :
563 0 : aAttrIter.OutParaAttr(false);
564 0 : m_rAttrOutput.RunText().append(m_rAttrOutput.Styles().makeStringAndClear());
565 :
566 0 : do {
567 0 : const sal_Int32 nNextAttr = std::min(aAttrIter.WhereNext(), nEnd);
568 0 : rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet();
569 :
570 0 : aAttrIter.OutAttr( nAktPos );
571 0 : m_rAttrOutput.RunText().append('{').append(m_rAttrOutput.Styles().makeStringAndClear()).append(SAL_NEWLINE_STRING);
572 0 : bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
573 0 : if( !bTxtAtr )
574 : {
575 0 : OUString aOut( aStr.copy( nAktPos, nNextAttr - nAktPos ) );
576 0 : m_rAttrOutput.RunText().append( msfilter::rtfutil::OutString( aOut, eChrSet ) );
577 : }
578 :
579 0 : m_rAttrOutput.RunText().append('}');
580 :
581 0 : nAktPos = nNextAttr;
582 0 : eChrSet = eNextChrSet;
583 0 : aAttrIter.NextPos();
584 : }
585 0 : while( nAktPos < nEnd );
586 0 : }
587 0 : m_rAttrOutput.RunText().append(OOO_STRING_SVTOOLS_RTF_PAR).append('}');
588 :
589 0 : SAL_INFO("sw.rtf", OSL_THIS_FUNC << " end");
590 0 : }
591 :
592 0 : void RtfSdrExport::EndShape( sal_Int32 nShapeElement )
593 : {
594 : SAL_INFO("sw.rtf", OSL_THIS_FUNC);
595 :
596 0 : if ( nShapeElement >= 0 )
597 : {
598 : // end of the shape
599 0 : m_rAttrOutput.RunText().append('}').append('}');
600 : }
601 0 : }
602 :
603 0 : sal_uInt32 RtfSdrExport::AddSdrObject( const SdrObject& rObj )
604 : {
605 0 : m_pSdrObject = &rObj;
606 0 : return EscherEx::AddSdrObject(rObj);
607 : }
608 :
609 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|