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 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <com/sun/star/embed/XEmbedPersist.hpp>
31 : : #include <com/sun/star/embed/Aspects.hpp>
32 : : #include <com/sun/star/embed/ElementModes.hpp>
33 : : #include <rtl/math.hxx>
34 : : #include <svtools/filter.hxx>
35 : : #include <svl/itemiter.hxx>
36 : : #include "svl/urihelper.hxx"
37 : :
38 : : #include <svtools/embedhlp.hxx>
39 : :
40 : : #include <vcl/virdev.hxx>
41 : : #include <vcl/svapp.hxx>
42 : :
43 : : #include <hintids.hxx>
44 : : #include <editeng/boxitem.hxx>
45 : : #include <editeng/shaditem.hxx>
46 : : #include <filter/msfilter/msoleexp.hxx>
47 : : #include <editeng/lrspitem.hxx> // SvxLRSpaceItem
48 : : #include <editeng/ulspitem.hxx>
49 : : #include <editeng/fhgtitem.hxx>
50 : : #include <svx/svdoole2.hxx>
51 : :
52 : : #include <unotools/ucbstreamhelper.hxx>
53 : : #include <fmtanchr.hxx>
54 : : #include <ndgrf.hxx>
55 : : #include <frmfmt.hxx> // class SwFlyFrmFmt
56 : : #include <grfatr.hxx> // class SwCropGrf
57 : : #include <ndole.hxx>
58 : : #include <ndtxt.hxx>
59 : : #include <fmtfsize.hxx>
60 : : #include <fmtornt.hxx>
61 : :
62 : : #include <writerfilter/doctok/sprmids.hxx>
63 : :
64 : : #include <doc.hxx>
65 : : #include "writerhelper.hxx"
66 : : #include "writerwordglue.hxx"
67 : : #include "ww8struc.hxx"
68 : : #include "wrtww8.hxx"
69 : : #include "ww8par.hxx"
70 : : #include "escher.hxx"
71 : :
72 : : #include "docsh.hxx"
73 : : #include <cstdio>
74 : :
75 : : #if OSL_DEBUG_LEVEL > 1
76 : : #include <stdio.h>
77 : : #endif
78 : :
79 : : using namespace ::com::sun::star;
80 : : using namespace nsFieldFlags;
81 : :
82 : : // ToDo:
83 : : // 5. Die MapModes, die Win nicht kann, umrechnen
84 : :
85 : : // OutGrf() wird fuer jeden GrafNode im Doc gerufen. Es wird ein PicLocFc-Sprm
86 : : // eingefuegt, der statt Adresse ein Magic sal_uLong enthaelt. Ausserdem wird
87 : : // in der Graf-Klasse der GrfNode-Ptr gemerkt ( fuers spaetere Ausgeben der
88 : : // Grafiken und Patchen der PicLocFc-Attribute )
89 : :
90 : 0 : void WW8Export::OutputGrfNode( const SwGrfNode& /*rNode*/ )
91 : : {
92 : : OSL_TRACE("WW8Export::OutputGrfNode( const SwGrfNode& )" );
93 : : OSL_ENSURE( mpParentFrame, "frame not set!" );
94 [ # # ]: 0 : if ( mpParentFrame )
95 : : {
96 : 0 : OutGrf( *mpParentFrame );
97 : 0 : pFib->fHasPic = 1;
98 : : }
99 : 0 : }
100 : :
101 : 0 : bool WW8Export::TestOleNeedsGraphic(const SwAttrSet& rSet,
102 : : SvStorageRef xOleStg, SvStorageRef xObjStg, String &rStorageName,
103 : : SwOLENode *pOLENd)
104 : : {
105 : 0 : bool bGraphicNeeded = false;
106 [ # # ]: 0 : SfxItemIter aIter( rSet );
107 : 0 : const SfxPoolItem* pItem = aIter.GetCurItem();
108 : :
109 [ # # # # ]: 0 : do {
[ # # ][ # # ]
[ # # ]
110 [ # # ]: 0 : switch (pItem->Which())
111 : : {
112 : : /*
113 : : For an inline object these properties are irrelevent because they
114 : : will be the same as the defaults that msword applies in their
115 : : absence, so if that is all that there is for these inline objects
116 : : then if there turns out to be enough information in the object
117 : : itself to regenerate the correct size and preview of the object
118 : : then we will not need to provide an additional graphics preview in
119 : : the data stream, which can save a lot of disk space.
120 : : */
121 : : case RES_FRM_SIZE:
122 : : case RES_CNTNT:
123 : : case RES_VERT_ORIENT:
124 : : case RES_ANCHOR:
125 : 0 : break;
126 : : default:
127 : 0 : bGraphicNeeded = true;
128 : : }
129 : 0 : } while( !bGraphicNeeded && !aIter.IsAtEnd() &&
130 : : 0 != ( pItem = aIter.NextItem() ) );
131 : :
132 : : /*
133 : : Now we must see if the object contains a preview itself which is equal to
134 : : the preview that we are currently using. If the graphics are equal then we
135 : : dont need to store another preview
136 : : */
137 [ # # ]: 0 : GDIMetaFile aWMF;
138 : 0 : long nX=0,nY=0;
139 [ # # ][ # # ]: 0 : if (!bGraphicNeeded && SwWW8ImplReader::ImportOleWMF(xOleStg,aWMF,nX,nY))
[ # # ][ # # ]
[ # # ]
[ # # # # ]
140 : : {
141 : : // bGraphicNeeded set to true is right / fixes #i51670#.
142 : 0 : bGraphicNeeded = true;
143 : 0 : Point aTmpPoint;
144 [ # # ]: 0 : Rectangle aRect( aTmpPoint, Size( nX, nY ) );
145 [ # # ]: 0 : Graphic aGraph(aWMF);
146 : :
147 : 0 : ErrCode nErr = ERRCODE_NONE;
148 [ # # ]: 0 : Rectangle aVisArea;
149 : 0 : sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
150 [ # # ]: 0 : if ( pOLENd )
151 [ # # ]: 0 : nAspect = pOLENd->GetAspect();
152 : : SdrOle2Obj *pRet = SvxMSDffManager::CreateSdrOLEFromStorage(
153 [ # # ][ # # ]: 0 : rStorageName,xObjStg,pDoc->GetDocStorage(),aGraph,aRect,aVisArea,0,nErr,0,nAspect);
154 : :
155 [ # # ]: 0 : if (pRet)
156 : : {
157 [ # # ]: 0 : uno::Reference< embed::XEmbeddedObject > xObj = pOLENd->GetOLEObj().GetOleRef();
158 [ # # ]: 0 : if ( xObj.is() )
159 : : {
160 : 0 : SvStream* pGraphicStream = NULL;
161 [ # # ][ # # ]: 0 : comphelper::EmbeddedObjectContainer aCnt( pDoc->GetDocStorage() );
162 : : try
163 : : {
164 : : uno::Reference< embed::XEmbedPersist > xPersist(
165 : : xObj,
166 [ # # ]: 0 : uno::UNO_QUERY_THROW );
167 : :
168 : : // it makes no sence to search the object in the container by reference since the object was created
169 : : // outside of the container and was not inserted there, only the name makes sence
170 : : pGraphicStream =
171 [ # # ][ # # ]: 0 : ::utl::UcbStreamHelper::CreateStream( aCnt.GetGraphicStream( xPersist->getEntryName() ) );
[ # # ][ # # ]
[ # # ]
172 : : }
173 [ # # ]: 0 : catch( const uno::Exception& )
174 : : {}
175 : :
176 : : OSL_ENSURE( pGraphicStream && !pGraphicStream->GetError(), "No graphic stream available!" );
177 [ # # ][ # # ]: 0 : if ( pGraphicStream && !pGraphicStream->GetError() )
[ # # ]
178 : : {
179 [ # # ]: 0 : Graphic aGr1;
180 [ # # ]: 0 : GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
181 [ # # ][ # # ]: 0 : if( rGF.ImportGraphic( aGr1, aEmptyStr, *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ) == GRFILTER_OK )
182 : : {
183 [ # # ]: 0 : Graphic aGr2;
184 [ # # ][ # # ]: 0 : delete pGraphicStream;
185 : : pGraphicStream =
186 [ # # ][ # # ]: 0 : ::utl::UcbStreamHelper::CreateStream( aCnt.GetGraphicStream( pRet->GetObjRef() ) );
[ # # ]
187 [ # # ][ # # ]: 0 : if( rGF.ImportGraphic( aGr2, aEmptyStr, *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ) == GRFILTER_OK )
188 : : {
189 [ # # ][ # # ]: 0 : if ( aGr1 == aGr2 )
190 : 0 : bGraphicNeeded = false;
191 [ # # ]: 0 : }
192 [ # # ]: 0 : }
193 : : }
194 : : else
195 [ # # ][ # # ]: 0 : delete pGraphicStream;
[ # # ]
196 : : }
197 : :
198 [ # # ][ # # ]: 0 : delete pRet;
199 [ # # ]: 0 : }
200 : : }
201 : : else
202 : 0 : bGraphicNeeded = true;
203 [ # # ][ # # ]: 0 : return bGraphicNeeded;
204 : : }
205 : :
206 : 0 : void WW8Export::OutputOLENode( const SwOLENode& rOLENode )
207 : : {
208 : : OSL_TRACE("WW8Export::OutputOLENode( const SwOLENode& rOLENode )" );
209 : : sal_uInt8 *pSpecOLE;
210 : : sal_uInt8 *pDataAdr;
211 : : short nSize;
212 : : static sal_uInt8 aSpecOLE_WW8[] = {
213 : : 0x03, 0x6a, 0, 0, 0, 0, // sprmCPicLocation
214 : : 0x0a, 0x08, 1, // sprmCFOLE2
215 : : 0x56, 0x08, 1 // sprmCFObj
216 : : };
217 : : static sal_uInt8 aSpecOLE_WW6[] = {
218 : : 68, 4, 0, 0, 0, 0, // sprmCPicLocation (len is 4)
219 : : 75, 1, // sprmCFOLE2
220 : : 118, 1 // sprmCFObj
221 : : };
222 : :
223 [ # # ]: 0 : if ( bWrtWW8 )
224 : : {
225 : 0 : pSpecOLE = aSpecOLE_WW8;
226 : 0 : nSize = sizeof( aSpecOLE_WW8 );
227 : : }
228 : : else
229 : : {
230 : 0 : pSpecOLE = aSpecOLE_WW6;
231 : 0 : nSize = sizeof( aSpecOLE_WW6 );
232 : : }
233 : 0 : pDataAdr = pSpecOLE + 2; //WW6 sprm is 1 but has 1 byte len as well.
234 : :
235 : 0 : SvStorageRef xObjStg = GetWriter().GetStorage().OpenSotStorage(
236 : : rtl::OUString(SL::aObjectPool), STREAM_READWRITE |
237 [ # # # # ]: 0 : STREAM_SHARE_DENYALL );
[ # # ]
238 : :
239 [ # # ]: 0 : if( xObjStg.Is() )
240 : : {
241 [ # # ]: 0 : uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode&>(rOLENode).GetOLEObj().GetOleRef());
242 [ # # ]: 0 : if( xObj.is() )
243 : : {
244 [ # # ]: 0 : const embed::XEmbeddedObject *pObj = xObj.get();
245 : 0 : WW8OleMap& rPointerToObjId = GetOLEMap();
246 : : //Don't want to use pointer ids, as is traditional, because we need
247 : : //to put this into a 32bit value, and on 64bit the bottom bits
248 : : //might collide and two unrelated ole objects end up considered the
249 : : //same. Don't want to simply start at 0 which is a special value
250 : 0 : sal_Int32 nPictureId = SAL_MAX_INT32 - rPointerToObjId.size();
251 : 0 : WW8OleMap::value_type entry = std::make_pair(pObj, nPictureId);
252 [ # # ]: 0 : std::pair<WW8OleMap::iterator, bool> aRes = rPointerToObjId.insert(entry);
253 : 0 : bool bIsNotDuplicate = aRes.second; //.second is false when element already existed
254 : 0 : nPictureId = aRes.first->second;
255 : 0 : Set_UInt32(pDataAdr, nPictureId);
256 [ # # ]: 0 : String sStorageName = rtl::OUString('_');
257 [ # # ][ # # ]: 0 : sStorageName += String::CreateFromInt32( nPictureId );
[ # # ]
258 : : SvStorageRef xOleStg = xObjStg->OpenSotStorage( sStorageName,
259 [ # # ]: 0 : STREAM_READWRITE| STREAM_SHARE_DENYALL );
260 [ # # ]: 0 : if( xOleStg.Is() )
261 : : {
262 : : /*
263 : : If this object storage has been written already don't
264 : : waste time rewriting it
265 : : */
266 [ # # ]: 0 : if (bIsNotDuplicate)
267 : : {
268 [ # # ]: 0 : sal_Int64 nAspect = rOLENode.GetAspect();
269 [ # # ]: 0 : svt::EmbeddedObjectRef aObjRef( xObj, nAspect );
270 [ # # ]: 0 : GetOLEExp().ExportOLEObject( aObjRef, *xOleStg );
271 [ # # ]: 0 : if ( nAspect == embed::Aspects::MSOLE_ICON )
272 : : {
273 : 0 : ::rtl::OUString aObjInfo( "\3ObjInfo" );
274 [ # # ][ # # ]: 0 : if ( !xOleStg->IsStream( aObjInfo ) )
[ # # ][ # # ]
275 : : {
276 : 0 : const sal_uInt8 pObjInfoData[] = { 0x40, 0x00, 0x03, 0x00 };
277 [ # # ][ # # ]: 0 : SvStorageStreamRef rObjInfoStream = xOleStg->OpenSotStream( aObjInfo );
[ # # ]
278 [ # # ][ # # ]: 0 : if ( rObjInfoStream.Is() && !rObjInfoStream->GetError() )
[ # # ]
279 : : {
280 [ # # ]: 0 : rObjInfoStream->Write( pObjInfoData, sizeof( pObjInfoData ) );
281 [ # # ]: 0 : xOleStg->Commit();
282 [ # # ]: 0 : }
283 : 0 : }
284 [ # # ]: 0 : }
285 : : }
286 : :
287 : : // write as embedded field - the other things will be done
288 : : // in the escher export
289 [ # # ]: 0 : String sServer(FieldString(ww::eEMBED));
290 [ # # ][ # # ]: 0 : sServer += xOleStg->GetUserName();
[ # # ]
291 [ # # ]: 0 : sServer += ' ';
292 : :
293 : : OutputField(0, ww::eEMBED, sServer, WRITEFIELD_START |
294 [ # # ]: 0 : WRITEFIELD_CMD_START | WRITEFIELD_CMD_END);
295 : :
296 [ # # ]: 0 : pChpPlc->AppendFkpEntry( Strm().Tell(),
297 [ # # ]: 0 : nSize, pSpecOLE );
298 : :
299 : 0 : bool bEndCR = true;
300 : : /*
301 : : In the word filter we only need a preview image for
302 : : floating images, and then only (the usual case) if the
303 : : object doesn't contain enough information to reconstruct
304 : : what we need.
305 : :
306 : : We don't need a graphic for inline objects, so we don't
307 : : even need the overhead of a graphic in that case.
308 : : */
309 : 0 : bool bGraphicNeeded = false;
310 : :
311 [ # # ]: 0 : if (mpParentFrame)
312 : : {
313 : 0 : bGraphicNeeded = true;
314 : :
315 [ # # ][ # # ]: 0 : if (mpParentFrame->IsInline())
316 : : {
317 : : const SwAttrSet& rSet =
318 : 0 : mpParentFrame->GetFrmFmt().GetAttrSet();
319 : 0 : bEndCR = false;
320 : : bGraphicNeeded = TestOleNeedsGraphic(rSet,
321 [ # # ][ # # ]: 0 : xOleStg, xObjStg, sStorageName, const_cast<SwOLENode*>(&rOLENode));
[ # # ]
322 : : }
323 : : }
324 : :
325 [ # # ]: 0 : if (!bGraphicNeeded)
326 [ # # ]: 0 : WriteChar(0x1);
327 : : else
328 : : {
329 : : /*
330 : : ##897##
331 : : We need to insert the graphic representation of
332 : : this object for the inline case, otherwise word
333 : : has no place to find the dimensions of the ole
334 : : object, and will not be able to draw it
335 : : */
336 [ # # ]: 0 : OutGrf(*mpParentFrame);
337 : : }
338 : :
339 : : OutputField(0, ww::eEMBED, aEmptyStr,
340 [ # # ]: 0 : WRITEFIELD_END | WRITEFIELD_CLOSE);
341 : :
342 [ # # ]: 0 : if (bEndCR) //No newline in inline case
343 [ # # ][ # # ]: 0 : WriteCR();
[ # # ][ # # ]
344 [ # # ][ # # ]: 0 : }
345 : 0 : }
346 [ # # ]: 0 : }
347 : 0 : }
348 : :
349 : 0 : void WW8Export::OutputLinkedOLE( const rtl::OUString& rOleId )
350 : : {
351 [ # # ]: 0 : uno::Reference< embed::XStorage > xDocStg = pDoc->GetDocStorage();
352 [ # # ][ # # ]: 0 : uno::Reference< embed::XStorage > xOleStg = xDocStg->openStorageElement( "OLELinks", embed::ElementModes::READ );
353 [ # # ][ # # ]: 0 : SotStorageRef xObjSrc = SotStorage::OpenOLEStorage( xOleStg, rOleId, STREAM_READ );
[ # # ]
354 : :
355 : 0 : SotStorageRef xObjStg = GetWriter().GetStorage().OpenSotStorage(
356 : : rtl::OUString(SL::aObjectPool), STREAM_READWRITE |
357 [ # # # # ]: 0 : STREAM_SHARE_DENYALL );
[ # # ]
358 : :
359 [ # # ][ # # ]: 0 : if( xObjStg.Is() && xObjSrc.Is() )
[ # # ]
360 : : {
361 : : SotStorageRef xOleDst = xObjStg->OpenSotStorage( rOleId,
362 [ # # ][ # # ]: 0 : STREAM_READWRITE | STREAM_SHARE_DENYALL );
[ # # ]
363 [ # # ]: 0 : if ( xOleDst.Is() )
364 [ # # ]: 0 : xObjSrc->CopyTo( xOleDst );
365 : :
366 [ # # ]: 0 : if ( !xOleDst->GetError( ) )
367 : : {
368 [ # # ]: 0 : xOleDst->Commit();
369 : :
370 : : // Ouput the cPicLocation attribute
371 [ # # ][ # # ]: 0 : ww::bytes* pBuf = new ww::bytes();
372 [ # # ]: 0 : GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CPicLocation );
373 [ # # ]: 0 : GetWriter().InsUInt32( *pBuf, rOleId.copy( 1 ).toInt32() );
374 : :
375 [ # # ]: 0 : GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CFOle2 );
376 [ # # ]: 0 : pBuf->push_back( 1 );
377 : :
378 [ # # ]: 0 : GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CFSpec );
379 [ # # ]: 0 : pBuf->push_back( 1 );
380 : :
381 [ # # ]: 0 : GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CFObj );
382 [ # # ]: 0 : pBuf->push_back( 1 );
383 : :
384 [ # # ][ # # ]: 0 : pChpPlc->AppendFkpEntry( Strm().Tell(), pBuf->size(), pBuf->data() );
[ # # ]
385 [ # # ]: 0 : delete pBuf;
386 [ # # ]: 0 : }
387 [ # # ][ # # ]: 0 : }
388 : 0 : }
389 : :
390 : 0 : void WW8Export::OutGrf(const sw::Frame &rFrame)
391 : : {
392 : : // GrfNode fuer spaeteres rausschreiben der Grafik merken
393 [ # # ]: 0 : pGrf->Insert(rFrame);
394 : :
395 [ # # ][ # # ]: 0 : pChpPlc->AppendFkpEntry( Strm().Tell(), pO->size(), pO->data() );
[ # # ]
396 : 0 : pO->clear();
397 : :
398 : : // #i29408#
399 : : // linked, as-character anchored graphics have to be exported as fields.
400 [ # # ]: 0 : const SwGrfNode* pGrfNd = rFrame.IsInline() && rFrame.GetContent()
401 [ # # # # ]: 0 : ? rFrame.GetContent()->GetGrfNode() : 0;
402 [ # # ][ # # ]: 0 : if ( pGrfNd && pGrfNd->IsLinkedFile() )
[ # # ]
403 : : {
404 [ # # ]: 0 : String sStr( FieldString(ww::eINCLUDEPICTURE) );
405 [ # # ]: 0 : sStr.APPEND_CONST_ASC(" \"");
406 : : {
407 [ # # ]: 0 : if ( pGrfNd )
408 : : {
409 [ # # ]: 0 : String aFileURL;
410 [ # # ]: 0 : pGrfNd->GetFileFilterNms( &aFileURL, 0 );
411 [ # # ][ # # ]: 0 : sStr += aFileURL;
412 : : }
413 : : }
414 [ # # ]: 0 : sStr.APPEND_CONST_ASC("\" \\d");
415 : :
416 : : OutputField( 0, ww::eINCLUDEPICTURE, sStr,
417 [ # # ][ # # ]: 0 : WRITEFIELD_START | WRITEFIELD_CMD_START | WRITEFIELD_CMD_END );
418 : : }
419 : :
420 [ # # ]: 0 : WriteChar( (char)1 ); // Grafik-Sonderzeichen in Haupttext einfuegen
421 : :
422 : : sal_uInt8 aArr[ 18 ];
423 : 0 : sal_uInt8* pArr = aArr;
424 : :
425 : 0 : const SwFrmFmt &rFlyFmt = rFrame.GetFrmFmt();
426 [ # # ]: 0 : const RndStdIds eAn = rFlyFmt.GetAttrSet().GetAnchor(false).GetAnchorId();
427 [ # # ]: 0 : if (eAn == FLY_AS_CHAR)
428 : : {
429 [ # # ]: 0 : sal_Int16 eVert = rFlyFmt.GetVertOrient().GetVertOrient();
430 [ # # ][ # # ]: 0 : if ((eVert == text::VertOrientation::CHAR_CENTER) || (eVert == text::VertOrientation::LINE_CENTER))
431 : : {
432 : 0 : bool bVert = false;
433 : : //The default for word in vertical text mode is to center,
434 : : //otherwise a sub/super script hack is employed
435 [ # # ][ # # ]: 0 : if (pOutFmtNode && pOutFmtNode->ISA(SwCntntNode) )
[ # # ][ # # ]
[ # # ]
436 : : {
437 : 0 : const SwTxtNode* pTxtNd = (const SwTxtNode*)pOutFmtNode;
438 [ # # ]: 0 : SwPosition aPos(*pTxtNd);
439 [ # # ][ # # ]: 0 : bVert = pDoc->IsInVerticalText(aPos) ? true : false;
440 : : }
441 [ # # ]: 0 : if (!bVert)
442 : : {
443 [ # # ]: 0 : SwTwips nHeight = rFlyFmt.GetFrmSize().GetHeight();
444 : 0 : nHeight/=20; //nHeight was in twips, want it in half points, but
445 : : //then half of total height.
446 : : long nFontHeight = ((const SvxFontHeightItem&)
447 [ # # ]: 0 : GetItem(RES_CHRATR_FONTSIZE)).GetHeight();
448 : 0 : nHeight-=nFontHeight/20;
449 : :
450 [ # # ]: 0 : if (bWrtWW8)
451 : 0 : Set_UInt16( pArr, NS_sprm::LN_CHpsPos );
452 : : else
453 : 0 : Set_UInt8( pArr, 101 );
454 : 0 : Set_UInt16( pArr, -((sal_Int16)nHeight));
455 : : }
456 : : }
457 : : }
458 : :
459 : : // sprmCFSpec
460 [ # # ]: 0 : if( bWrtWW8 )
461 : 0 : Set_UInt16( pArr, 0x855 );
462 : : else
463 : 0 : Set_UInt8( pArr, 117 );
464 : 0 : Set_UInt8( pArr, 1 );
465 : :
466 : : // sprmCPicLocation
467 [ # # ]: 0 : if( bWrtWW8 )
468 : 0 : Set_UInt16( pArr, NS_sprm::LN_CPicLocation );
469 : : else
470 : : {
471 : 0 : Set_UInt8( pArr, 68 );
472 : 0 : Set_UInt8( pArr, 4 );
473 : : }
474 : 0 : Set_UInt32( pArr, GRF_MAGIC_321 );
475 : :
476 : : // Magic variieren, damit verschiedene Grafik-Attribute nicht
477 : : // gemerged werden
478 : : static sal_uInt8 nAttrMagicIdx = 0;
479 : 0 : --pArr;
480 : 0 : Set_UInt8( pArr, nAttrMagicIdx++ );
481 [ # # ][ # # ]: 0 : pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr );
482 : :
483 : : // #i75464#
484 : : // Check, if graphic isn't exported as-character anchored.
485 : : // Otherwise, an additional paragraph is exported for a graphic, which is
486 : : // forced to be treated as inline, because it's anchored inside another frame.
487 [ # # ][ # # ]: 0 : if ( !rFrame.IsInline() &&
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
488 [ # # ]: 0 : ( ((eAn == FLY_AT_PARA) && ( bWrtWW8 || !IsInTable() )) ||
489 : : (eAn == FLY_AT_PAGE)) )
490 : : {
491 [ # # ]: 0 : WriteChar( (char)0x0d ); // umgebenden Rahmen mit CR abschliessen
492 : :
493 : : static sal_uInt8 nSty[2] = { 0, 0 };
494 [ # # ]: 0 : pO->insert( pO->end(), nSty, nSty+2 ); // Style #0
495 : 0 : bool bOldGrf = bOutGrf;
496 : 0 : bOutGrf = true;
497 : :
498 [ # # ]: 0 : OutputFormat( rFrame.GetFrmFmt(), false, false, true ); // Fly-Attrs
499 : :
500 : 0 : bOutGrf = bOldGrf;
501 [ # # ][ # # ]: 0 : pPapPlc->AppendFkpEntry( Strm().Tell(), pO->size(), pO->data() );
[ # # ]
502 : 0 : pO->clear();
503 : : }
504 : : // #i29408#
505 : : // linked, as-character anchored graphics have to be exported as fields.
506 [ # # ][ # # ]: 0 : else if ( pGrfNd && pGrfNd->IsLinkedFile() )
[ # # ]
507 : : {
508 [ # # ][ # # ]: 0 : OutputField( 0, ww::eINCLUDEPICTURE, String(), WRITEFIELD_CLOSE );
[ # # ]
509 : : }
510 : 0 : }
511 : :
512 : 0 : GraphicDetails& GraphicDetails::operator=(const GraphicDetails &rOther)
513 : : {
514 : 0 : maFly = rOther.maFly;
515 : 0 : mnPos = rOther.mnPos;
516 : 0 : mnWid = rOther.mnWid;
517 : 0 : mnHei = rOther.mnHei;
518 : 0 : return *this;
519 : : }
520 : :
521 : 0 : void SwWW8WrGrf::Insert(const sw::Frame &rFly)
522 : : {
523 : 0 : const Size aSize( rFly.GetLayoutSize() );
524 : 0 : const sal_uInt16 nWidth = static_cast< sal_uInt16 >(aSize.Width());
525 : 0 : const sal_uInt16 nHeight = static_cast< sal_uInt16 >(aSize.Height());
526 [ # # ][ # # ]: 0 : maDetails.push_back(GraphicDetails(rFly, nWidth, nHeight));
[ # # ]
527 : 0 : }
528 : :
529 : 0 : void SwWW8WrGrf::WritePICFHeader(SvStream& rStrm, const sw::Frame &rFly,
530 : : sal_uInt16 mm, sal_uInt16 nWidth, sal_uInt16 nHeight, const SwAttrSet* pAttrSet)
531 : : {
532 : 0 : sal_Int16 nXSizeAdd = 0, nYSizeAdd = 0;
533 : 0 : sal_Int16 nCropL = 0, nCropR = 0, nCropT = 0, nCropB = 0;
534 : :
535 : : // Crop-AttributInhalt in Header schreiben ( falls vorhanden )
536 : : const SfxPoolItem* pItem;
537 [ # # ][ # # ]: 0 : if (pAttrSet && (SFX_ITEM_ON
[ # # ]
538 [ # # ]: 0 : == pAttrSet->GetItemState(RES_GRFATR_CROPGRF, false, &pItem)))
539 : : {
540 : 0 : const SwCropGrf& rCr = *(SwCropGrf*)pItem;
541 : 0 : nCropL = (sal_Int16)rCr.GetLeft();
542 : 0 : nCropR = (sal_Int16)rCr.GetRight();
543 : 0 : nCropT = (sal_Int16)rCr.GetTop();
544 : 0 : nCropB = (sal_Int16)rCr.GetBottom();
545 : 0 : nXSizeAdd = nXSizeAdd - (sal_Int16)( rCr.GetLeft() + rCr.GetRight() );
546 : 0 : nYSizeAdd = nYSizeAdd - (sal_Int16)( rCr.GetTop() + rCr.GetBottom() );
547 : : }
548 : :
549 : 0 : Size aGrTwipSz(rFly.GetSize());
550 : 0 : bool bWrtWW8 = rWrt.bWrtWW8;
551 [ # # ]: 0 : sal_uInt16 nHdrLen = bWrtWW8 ? 0x44 : 0x3A;
552 : :
553 : 0 : sal_uInt8 aArr[ 0x44 ] = { 0 };
554 : :
555 : 0 : sal_uInt8* pArr = aArr + 0x2E; //Do borders first
556 : :
557 : 0 : const SwAttrSet& rAttrSet = rFly.GetFrmFmt().GetAttrSet();
558 [ # # ][ # # ]: 0 : if (SFX_ITEM_ON == rAttrSet.GetItemState(RES_BOX, false, &pItem))
559 : : {
560 : 0 : const SvxBoxItem* pBox = (const SvxBoxItem*)pItem;
561 [ # # ]: 0 : if( pBox )
562 : : {
563 : 0 : bool bShadow = false; // Shadow ?
564 : : const SvxShadowItem* pSI =
565 [ # # ]: 0 : sw::util::HasItem<SvxShadowItem>(rAttrSet, RES_SHADOW);
566 [ # # ]: 0 : if (pSI)
567 : : {
568 : 0 : bShadow = (pSI->GetLocation() != SVX_SHADOW_NONE) &&
569 [ # # ][ # # ]: 0 : (pSI->GetWidth() != 0);
570 : : }
571 : :
572 : : sal_uInt8 aLnArr[4] = { BOX_LINE_TOP, BOX_LINE_LEFT,
573 : 0 : BOX_LINE_BOTTOM, BOX_LINE_RIGHT };
574 [ # # ]: 0 : for( sal_uInt8 i = 0; i < 4; ++i )
575 : : {
576 [ # # ]: 0 : const ::editeng::SvxBorderLine* pLn = pBox->GetLine( aLnArr[ i ] );
577 : 0 : WW8_BRC aBrc;
578 [ # # ]: 0 : if (pLn)
579 : : {
580 : : aBrc = rWrt.TranslateBorderLine( *pLn,
581 [ # # ][ # # ]: 0 : pBox->GetDistance( aLnArr[ i ] ), bShadow );
582 : : }
583 : :
584 : : //use importer logic to determine how large the exported
585 : : //border will really be in word and adjust accordingly
586 : : short nSpacing;
587 : 0 : short nThick = aBrc.DetermineBorderProperties(!bWrtWW8,
588 [ # # ]: 0 : &nSpacing);
589 [ # # ]: 0 : switch (aLnArr[ i ])
590 : : {
591 : : case BOX_LINE_TOP:
592 : : case BOX_LINE_BOTTOM:
593 [ # # ]: 0 : nHeight -= bShadow ? nThick*2 : nThick;
594 : 0 : nHeight = nHeight - nSpacing;
595 : 0 : break;
596 : : case BOX_LINE_LEFT:
597 : : case BOX_LINE_RIGHT:
598 : : default:
599 [ # # ]: 0 : nWidth -= bShadow ? nThick*2 : nThick;
600 : 0 : nWidth = nWidth - nSpacing;
601 : 0 : break;
602 : : }
603 : 0 : memcpy( pArr, &aBrc.aBits1, 2);
604 : 0 : pArr+=2;
605 : :
606 [ # # ]: 0 : if( bWrtWW8 )
607 : : {
608 : 0 : memcpy( pArr, &aBrc.aBits2, 2);
609 : 0 : pArr+=2;
610 : : }
611 : : }
612 : : }
613 : : }
614 : :
615 : 0 : pArr = aArr + 4; //skip lcb
616 : 0 : Set_UInt16( pArr, nHdrLen ); // set cbHeader
617 : :
618 : 0 : Set_UInt16( pArr, mm ); // set mm
619 : :
620 : : /*
621 : : Just in case our original size is too big to fit inside a ushort we can
622 : : substitute the final size and loose on retaining the scaling factor but
623 : : still keep the correct display size anyway.
624 : : */
625 [ # # # # : 0 : if ( (aGrTwipSz.Width() > SHRT_MAX) || (aGrTwipSz.Height() > SHRT_MAX)
# # ][ # # ]
[ # # ]
626 : 0 : || (aGrTwipSz.Width() < 0 ) || (aGrTwipSz.Height() < 0) )
627 : : {
628 : 0 : aGrTwipSz.Width() = nWidth;
629 : 0 : aGrTwipSz.Height() = nHeight;
630 : : }
631 : : using namespace sw::types;
632 : : // set xExt & yExt
633 [ # # ]: 0 : Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Width() * 254L / 144));
634 [ # # ]: 0 : Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Height() * 254L / 144));
635 : 0 : pArr += 16;
636 : : // skip hMF & rcWinMF
637 : : // set dxaGoal & dyaGoal
638 [ # # ]: 0 : Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Width()));
639 [ # # ]: 0 : Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Height()));
640 : :
641 [ # # ]: 0 : if( aGrTwipSz.Width() + nXSizeAdd ) // set mx
642 : : {
643 : 0 : double fVal = nWidth * 1000.0 / (aGrTwipSz.Width() + nXSizeAdd);
644 : 0 : Set_UInt16( pArr, (sal_uInt16)::rtl::math::round(fVal) );
645 : : }
646 : : else
647 : 0 : pArr += 2;
648 : :
649 [ # # ]: 0 : if( aGrTwipSz.Height() + nYSizeAdd ) // set my
650 : : {
651 : 0 : double fVal = nHeight * 1000.0 / (aGrTwipSz.Height() + nYSizeAdd);
652 : 0 : Set_UInt16( pArr, (sal_uInt16)::rtl::math::round(fVal) );
653 : : }
654 : : else
655 : 0 : pArr += 2;
656 : :
657 : 0 : Set_UInt16( pArr, nCropL ); // set dxaCropLeft
658 : 0 : Set_UInt16( pArr, nCropT ); // set dyaCropTop
659 : 0 : Set_UInt16( pArr, nCropR ); // set dxaCropRight
660 : 0 : Set_UInt16( pArr, nCropB ); // set dyaCropBottom
661 : :
662 [ # # ]: 0 : rStrm.Write( aArr, nHdrLen );
663 : 0 : }
664 : :
665 : 0 : void SwWW8WrGrf::WriteGrfFromGrfNode(SvStream& rStrm, const SwGrfNode &rGrfNd,
666 : : const sw::Frame &rFly, sal_uInt16 nWidth, sal_uInt16 nHeight)
667 : : {
668 [ # # ]: 0 : if (rGrfNd.IsLinkedFile()) // Linked File
669 : : {
670 [ # # ]: 0 : String aFileN;
671 [ # # ]: 0 : rGrfNd.GetFileFilterNms( &aFileN, 0 );
672 : :
673 : 0 : sal_uInt16 mm = 94; // 94 = BMP, GIF
674 : :
675 : : WritePICFHeader(rStrm, rFly, mm, nWidth, nHeight,
676 [ # # ][ # # ]: 0 : rGrfNd.GetpSwAttrSet());
677 [ # # ]: 0 : rStrm << (sal_uInt8)aFileN.Len(); // Pascal-String schreiben
678 : : SwWW8Writer::WriteString8(rStrm, aFileN, false,
679 [ # # ][ # # ]: 0 : RTL_TEXTENCODING_MS_1252);
680 : : }
681 : : else // Embedded File oder DDE oder so was
682 : : {
683 [ # # ]: 0 : if (rWrt.bWrtWW8)
684 : : {
685 : : WritePICFHeader(rStrm, rFly, 0x64, nWidth, nHeight,
686 [ # # ][ # # ]: 0 : rGrfNd.GetpSwAttrSet());
687 [ # # ]: 0 : SwBasicEscherEx aInlineEscher(&rStrm, rWrt);
688 [ # # ]: 0 : aInlineEscher.WriteGrfFlyFrame(rFly.GetFrmFmt(), 0x401);
689 [ # # ][ # # ]: 0 : aInlineEscher.WritePictures();
690 : : }
691 : : else
692 : : {
693 [ # # ]: 0 : Graphic& rGrf = const_cast<Graphic&>(rGrfNd.GetGrf());
694 [ # # ]: 0 : bool bSwapped = rGrf.IsSwapOut() ? true : false;
695 : : // immer ueber den Node einswappen!
696 [ # # ]: 0 : const_cast<SwGrfNode&>(rGrfNd).SwapIn();
697 : :
698 [ # # ]: 0 : GDIMetaFile aMeta;
699 [ # # ]: 0 : switch (rGrf.GetType())
[ # # # ]
700 : : {
701 : : case GRAPHIC_BITMAP: // Bitmap -> in Metafile abspielen
702 : : {
703 [ # # ]: 0 : VirtualDevice aVirt;
704 [ # # ]: 0 : aMeta.Record(&aVirt);
705 [ # # ][ # # ]: 0 : aVirt.DrawBitmap( Point( 0,0 ), rGrf.GetBitmap() );
[ # # ]
706 [ # # ]: 0 : aMeta.Stop();
707 [ # # ]: 0 : aMeta.WindStart();
708 [ # # ][ # # ]: 0 : aMeta.SetPrefMapMode( rGrf.GetPrefMapMode());
[ # # ]
709 [ # # ][ # # ]: 0 : aMeta.SetPrefSize( rGrf.GetPrefSize());
710 : : }
711 : 0 : break;
712 : : case GRAPHIC_GDIMETAFILE : // GDI ( =SV ) Metafile
713 [ # # ][ # # ]: 0 : aMeta = rGrf.GetGDIMetaFile();
714 : 0 : break;
715 : : default:
716 : 0 : return;
717 : : }
718 : :
719 : : WritePICFHeader(rStrm, rFly, 8, nWidth, nHeight,
720 [ # # ][ # # ]: 0 : rGrfNd.GetpSwAttrSet());
721 [ # # ]: 0 : WriteWindowMetafileBits(rStrm, aMeta);
722 : :
723 [ # # ]: 0 : if (bSwapped)
724 [ # # ][ # # ]: 0 : rGrf.SwapOut();
[ # # ]
725 : : }
726 : : }
727 : : }
728 : :
729 : 0 : void SwWW8WrGrf::WriteGraphicNode(SvStream& rStrm, const GraphicDetails &rItem)
730 : : {
731 : 0 : sal_uInt16 nWidth = rItem.mnWid;
732 : 0 : sal_uInt16 nHeight = rItem.mnHei;
733 : 0 : sal_uInt32 nPos = rStrm.Tell(); // Grafik-Anfang merken
734 : :
735 : 0 : const sw::Frame &rFly = rItem.maFly;
736 [ # # # # ]: 0 : switch (rFly.GetWriterType())
737 : : {
738 : : case sw::Frame::eGraphic:
739 : : {
740 : 0 : const SwNode *pNode = rItem.maFly.GetContent();
741 [ # # ]: 0 : const SwGrfNode *pNd = pNode ? pNode->GetGrfNode() : 0;
742 : : OSL_ENSURE(pNd, "Impossible");
743 [ # # ]: 0 : if (pNd)
744 [ # # ]: 0 : WriteGrfFromGrfNode(rStrm, *pNd, rItem.maFly, nWidth, nHeight);
745 : : }
746 : 0 : break;
747 : : case sw::Frame::eOle:
748 : : {
749 : : #ifdef OLE_PREVIEW_AS_EMF
750 : 0 : const SwNode *pNode = rItem.maFly.GetContent();
751 [ # # ]: 0 : const SwOLENode *pNd = pNode ? pNode->GetOLENode() : 0;
752 : : OSL_ENSURE(pNd, "Impossible");
753 [ # # ]: 0 : if (!rWrt.bWrtWW8)
754 : : {
755 : 0 : SwOLENode *pOleNd = const_cast<SwOLENode*>(pNd);
756 : : OSL_ENSURE( pOleNd, " Wer hat den OleNode versteckt ?" );
757 : 0 : SwOLEObj& rSObj= pOleNd->GetOLEObj();
758 [ # # ]: 0 : uno::Reference < embed::XEmbeddedObject > rObj( rSObj.GetOleRef() );
759 : :
760 [ # # ][ # # ]: 0 : comphelper::EmbeddedObjectContainer aCnt( pOleNd->GetDoc()->GetDocStorage() );
761 : :
762 [ # # ][ # # ]: 0 : SvStream* pGraphicStream = ::utl::UcbStreamHelper::CreateStream( aCnt.GetGraphicStream( rObj ) );
763 : : OSL_ENSURE( pGraphicStream && !pGraphicStream->GetError(), "No graphic stream available!" );
764 [ # # ][ # # ]: 0 : if ( pGraphicStream && !pGraphicStream->GetError() )
[ # # ]
765 : : {
766 [ # # ]: 0 : Graphic aGr;
767 [ # # ]: 0 : GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
768 [ # # ][ # # ]: 0 : if( rGF.ImportGraphic( aGr, aEmptyStr, *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ) == GRFILTER_OK )
769 : : {
770 : : //TODO/LATER: do we really want to use GDIMetafile?!
771 [ # # ]: 0 : GDIMetaFile aMtf;
772 [ # # ][ # # ]: 0 : aMtf = aGr.GetGDIMetaFile();
773 [ # # ]: 0 : aMtf.WindStart();
774 : : aMtf.Play(Application::GetDefaultDevice(), Point(0, 0),
775 [ # # ][ # # ]: 0 : Size(2880, 2880));
776 : : WritePICFHeader(rStrm, rFly, 8, nWidth, nHeight,
777 [ # # ][ # # ]: 0 : pNd->GetpSwAttrSet());
778 [ # # ][ # # ]: 0 : WriteWindowMetafileBits(rStrm, aMtf);
779 [ # # ]: 0 : }
780 : : }
781 : : else
782 [ # # ][ # # ]: 0 : delete pGraphicStream;
[ # # ]
783 : : }
784 : : else
785 : : {
786 : : //Convert this ole2 preview in ww8+ to an EMF for better unicode
787 : : //support (note that at this moment this breaks StarSymbol
788 : : //using graphics because I need to embed starsymbol in exported
789 : : //documents.
790 : : WritePICFHeader(rStrm, rFly, 0x64, nWidth, nHeight,
791 [ # # ][ # # ]: 0 : pNd->GetpSwAttrSet());
792 [ # # ]: 0 : SwBasicEscherEx aInlineEscher(&rStrm, rWrt);
793 [ # # ]: 0 : aInlineEscher.WriteOLEFlyFrame(rFly.GetFrmFmt(), 0x401);
794 [ # # ][ # # ]: 0 : aInlineEscher.WritePictures();
795 : : }
796 : : #else
797 : : // cast away const
798 : : SwOLENode *pOleNd = const_cast<SwOLENode*>(pNd);
799 : : OSL_ENSURE( pOleNd, " Wer hat den OleNode versteckt ?" );
800 : : SwOLEObj& rSObj= pOleNd->GetOLEObj();
801 : :
802 : : // TODO/LATER: do we need to load object?
803 : : Graphic* pGr = SdrOle2Obj::GetGraphicFromObject( pOleNd->GetDoc()->GetDocStorage(), rObj );
804 : :
805 : : //TODO/LATER: do we really want to use GDIMetafile?!
806 : : GDIMetaFile aMtf;
807 : : if ( pGr )
808 : : aMtf = pGr->GetGDIMetaFile();
809 : :
810 : : Size aS(aMtf.GetPrefSize());
811 : : aMtf.WindStart();
812 : : aMtf.Play(Application::GetDefaultDevice(), Point(0, 0),
813 : : Size(2880, 2880));
814 : :
815 : : WritePICFHeader(rStrm, rFly, 8, nWidth, nHeight,
816 : : pNd->GetpSwAttrSet());
817 : : WriteWindowMetafileBits(rStrm, aMtf);
818 : : delete pGr;
819 : : #endif
820 : : }
821 : 0 : break;
822 : : case sw::Frame::eDrawing:
823 : : case sw::Frame::eTxtBox:
824 : : case sw::Frame::eFormControl:
825 : : OSL_ENSURE(rWrt.bWrtWW8,
826 : : "You can't try and export these in WW8 format, a filter bug");
827 : : /*
828 : : #i3958# We only export an empty dummy picture frame here, this is
829 : : what word does the escher export should contain an anchored to
830 : : character element which is drawn over this dummy and the whole
831 : : shebang surrounded with a SHAPE field. This isn't *my* hack :-),
832 : : its what word does.
833 : : */
834 [ # # ]: 0 : if (rWrt.bWrtWW8)
835 : : {
836 [ # # ]: 0 : WritePICFHeader(rStrm, rFly, 0x64, nWidth, nHeight);
837 [ # # ]: 0 : SwBasicEscherEx aInlineEscher(&rStrm, rWrt);
838 [ # # ][ # # ]: 0 : aInlineEscher.WriteEmptyFlyFrame(rFly.GetFrmFmt(), 0x401);
839 : : }
840 : 0 : break;
841 : : default:
842 : : OSL_ENSURE(!this,
843 : : "Some inline export not implemented, remind cmc before we ship :-)");
844 : 0 : break;
845 : : }
846 : :
847 : 0 : sal_uInt32 nPos2 = rStrm.Tell(); // Ende merken
848 [ # # ]: 0 : rStrm.Seek( nPos );
849 : : SVBT32 nLen;
850 : 0 : UInt32ToSVBT32( nPos2 - nPos, nLen ); // Grafik-Laenge ausrechnen
851 [ # # ]: 0 : rStrm.Write( nLen, 4 ); // im Header einpatchen
852 [ # # ]: 0 : rStrm.Seek( nPos2 ); // Pos wiederherstellen
853 : 0 : }
854 : :
855 : : // SwWW8WrGrf::Write() wird nach dem Text gerufen. Es schreibt die alle
856 : : // Grafiken raus und merkt sich die File-Positionen der Grafiken, damit
857 : : // beim Schreiben der Attribute die Positionen in die PicLocFc-Sprms
858 : : // eingepatcht werden koennen.
859 : : // Das Suchen in den Attributen nach dem Magic sal_uLong und das Patchen
860 : : // passiert beim Schreiben der Attribute. Die SwWW8WrGrf-Klasse liefert
861 : : // hierfuer nur mit GetFPos() sequentiell die Positionen.
862 : 9 : void SwWW8WrGrf::Write()
863 : : {
864 : 9 : SvStream& rStrm = *rWrt.pDataStrm;
865 : 9 : myiter aEnd = maDetails.end();
866 [ + - ][ - + ]: 9 : for (myiter aIter = maDetails.begin(); aIter != aEnd; ++aIter)
867 : : {
868 : 0 : sal_uInt32 nPos = rStrm.Tell(); // auf 4 Bytes alignen
869 [ # # ]: 0 : if( nPos & 0x3 )
870 [ # # ]: 0 : SwWW8Writer::FillCount( rStrm, 4 - ( nPos & 0x3 ) );
871 : :
872 : 0 : bool bDuplicated = false;
873 [ # # ][ # # ]: 0 : for (myiter aIter2 = maDetails.begin(); aIter2 != aIter; ++aIter2)
874 : : {
875 [ # # ]: 0 : if (*aIter2 == *aIter)
876 : : {
877 : 0 : aIter->mnPos = aIter2->mnPos;
878 : 0 : bDuplicated = true;
879 : 0 : break;
880 : : }
881 : : }
882 : :
883 [ # # ]: 0 : if (!bDuplicated)
884 : : {
885 : 0 : aIter->mnPos = rStrm.Tell();
886 [ # # ]: 0 : WriteGraphicNode(rStrm, *aIter);
887 : : }
888 : : }
889 [ + - ][ + - ]: 63 : }
890 : :
891 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|