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