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