update dev300-m58
[ooovba.git] / sw / source / filter / ww8 / wrtww8gr.cxx
blobed3d1b3b7e16738c4aede78c974182ba17da8c96
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: wrtww8gr.cxx,v $
10 * $Revision: 1.54 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
34 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
36 #include <com/sun/star/embed/XEmbedPersist.hpp>
37 #include <com/sun/star/embed/Aspects.hpp>
38 #include <rtl/math.hxx>
39 #include <svtools/filter.hxx>
40 #include <svtools/itemiter.hxx>
41 #include "svtools/urihelper.hxx"
43 #include <svtools/embedhlp.hxx>
45 #include <vcl/virdev.hxx>
46 #include <vcl/svapp.hxx>
48 #include <hintids.hxx>
49 #include <svx/boxitem.hxx>
50 #include <svx/shaditem.hxx>
51 #include <svx/shaditem.hxx>
52 #include <svx/msoleexp.hxx>
53 #include <svx/lrspitem.hxx> // SvxLRSpaceItem
54 #include <svx/ulspitem.hxx>
55 #include <svx/fhgtitem.hxx>
56 #include <svx/svdoole2.hxx>
58 #include <unotools/ucbstreamhelper.hxx>
59 #include <fmtanchr.hxx>
60 #include <ndgrf.hxx>
61 #include <frmfmt.hxx> // class SwFlyFrmFmt
62 #include <grfatr.hxx> // class SwCropGrf
63 #include <ndole.hxx>
64 #include <ndtxt.hxx>
65 #include <fmtfsize.hxx>
66 #include <fmtornt.hxx>
68 #include <writerfilter/doctok/sprmids.hxx>
70 #include <doc.hxx>
71 #include "writerhelper.hxx"
72 #include "writerwordglue.hxx"
73 #include "ww8struc.hxx"
74 #include "wrtww8.hxx"
75 #include "ww8par.hxx"
76 #include "escher.hxx"
78 #include "docsh.hxx"
80 using namespace ::com::sun::star;
81 using namespace nsFieldFlags;
83 // Damit KA debuggen kann, ohne sich den ganzen Writer zu holen, ist
84 // temporaer dieses Debug gesetzt. Ist ausserdem noch das passende IniFlag
85 // gesetzt, dann werden in d:\ Hilfsdateien erzeugt.
86 // !! sollte demnaechst wieder entfernt werden !!
87 // #define DEBUG_KA
90 // ToDo:
91 // 5. Die MapModes, die Win nicht kann, umrechnen
93 // OutGrf() wird fuer jeden GrafNode im Doc gerufen. Es wird ein PicLocFc-Sprm
94 // eingefuegt, der statt Adresse ein Magic ULONG enthaelt. Ausserdem wird
95 // in der Graf-Klasse der GrfNode-Ptr gemerkt ( fuers spaetere Ausgeben der
96 // Grafiken und Patchen der PicLocFc-Attribute )
98 void WW8Export::OutputGrfNode( const SwGrfNode& /*rNode*/ )
100 #if OSL_DEBUG_LEVEL > 0
101 fprintf( stderr, "WW8Export::OutputGrfNode( const SwGrfNode& )\n" );
102 #endif
103 ASSERT( mpParentFrame, "frame not set!" );
104 if ( mpParentFrame )
106 OutGrf( *mpParentFrame );
107 pFib->fHasPic = 1;
111 bool WW8Export::TestOleNeedsGraphic(const SwAttrSet& rSet,
112 SvStorageRef xOleStg, SvStorageRef xObjStg, String &rStorageName,
113 SwOLENode *pOLENd)
115 #ifdef NO_OLE_SIZE_OPTIMIZE
116 return true;
117 #else
118 bool bGraphicNeeded = false;
119 SfxItemIter aIter( rSet );
120 const SfxPoolItem* pItem = aIter.GetCurItem();
122 do {
123 switch (pItem->Which())
126 For an inline object these properties are irrelevent because they
127 will be the same as the defaults that msword applies in their
128 absence, so if that is all that there is for these inline objects
129 then if there turns out to be enough information in the object
130 itself to regenerate the correct size and preview of the object
131 then we will not need to provide an additional graphics preview in
132 the data stream, which can save a lot of disk space.
134 case RES_FRM_SIZE:
135 case RES_CNTNT:
136 case RES_VERT_ORIENT:
137 case RES_ANCHOR:
138 break;
139 default:
140 bGraphicNeeded = true;
142 } while( !bGraphicNeeded && !aIter.IsAtEnd() &&
143 0 != ( pItem = aIter.NextItem() ) );
146 Now we must see if the object contains a preview itself which is equal to
147 the preview that we are currently using. If the graphics are equal then we
148 dont need to store another preview
150 GDIMetaFile aWMF;
151 long nX=0,nY=0;
152 if (!bGraphicNeeded && SwWW8ImplReader::ImportOleWMF(xOleStg,aWMF,nX,nY))
154 // bGraphicNeeded set to true is right / fixes #i51670#.
155 bGraphicNeeded = true;
156 Point aTmpPoint;
157 Rectangle aRect( aTmpPoint, Size( nX, nY ) );
158 Graphic aGraph(aWMF);
160 ErrCode nErr = ERRCODE_NONE;
161 Rectangle aVisArea;
162 sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
163 if ( pOLENd )
164 nAspect = pOLENd->GetAspect();
165 SdrOle2Obj *pRet = SvxMSDffManager::CreateSdrOLEFromStorage(
166 rStorageName,xObjStg,pDoc->GetDocStorage(),aGraph,aRect,aVisArea,0,nErr,0,nAspect);
168 if (pRet)
170 uno::Reference< embed::XEmbeddedObject > xObj = pOLENd->GetOLEObj().GetOleRef();
171 if ( xObj.is() )
173 SvStream* pGraphicStream = NULL;
174 comphelper::EmbeddedObjectContainer aCnt( pDoc->GetDocStorage() );
177 uno::Reference< embed::XEmbedPersist > xPersist(
178 xObj,
179 uno::UNO_QUERY_THROW );
181 // it makes no sence to search the object in the container by reference since the object was created
182 // outside of the container and was not inserted there, only the name makes sence
183 pGraphicStream =
184 ::utl::UcbStreamHelper::CreateStream( aCnt.GetGraphicStream( xPersist->getEntryName() ) );
186 catch( uno::Exception& )
189 DBG_ASSERT( pGraphicStream && !pGraphicStream->GetError(), "No graphic stream available!" );
190 if ( pGraphicStream && !pGraphicStream->GetError() )
192 Graphic aGr1;
193 GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
194 if( pGF->ImportGraphic( aGr1, aEmptyStr, *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ) == GRFILTER_OK )
196 Graphic aGr2;
197 delete pGraphicStream;
198 pGraphicStream =
199 ::utl::UcbStreamHelper::CreateStream( aCnt.GetGraphicStream( pRet->GetObjRef() ) );
200 if( pGF->ImportGraphic( aGr2, aEmptyStr, *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ) == GRFILTER_OK )
202 if ( aGr1 == aGr2 )
203 bGraphicNeeded = false;
207 else
208 delete pGraphicStream;
211 delete pRet;
214 else
215 bGraphicNeeded = true;
216 return bGraphicNeeded;
217 #endif
220 void WW8Export::OutputOLENode( const SwOLENode& rOLENode )
222 #if OSL_DEBUG_LEVEL > 0
223 fprintf( stderr, "WW8Export::OutputOLENode( const SwOLENode& rOLENode )\n" );
224 #endif
225 BYTE *pSpecOLE;
226 BYTE *pDataAdr;
227 short nSize;
228 static BYTE aSpecOLE_WW8[] = {
229 0x03, 0x6a, 0, 0, 0, 0, // sprmCPicLocation
230 0x0a, 0x08, 1, // sprmCFOLE2
231 0x56, 0x08, 1 // sprmCFObj
233 static BYTE aSpecOLE_WW6[] = {
234 68, 4, 0, 0, 0, 0, // sprmCPicLocation (len is 4)
235 75, 1, // sprmCFOLE2
236 118, 1 // sprmCFObj
239 if ( bWrtWW8 )
241 pSpecOLE = aSpecOLE_WW8;
242 nSize = sizeof( aSpecOLE_WW8 );
244 else
246 pSpecOLE = aSpecOLE_WW6;
247 nSize = sizeof( aSpecOLE_WW6 );
249 pDataAdr = pSpecOLE + 2; //WW6 sprm is 1 but has 1 byte len as well.
251 SvStorageRef xObjStg = GetWriter().GetStorage().OpenSotStorage(
252 CREATE_CONST_ASC(SL::aObjectPool), STREAM_READWRITE |
253 STREAM_SHARE_DENYALL );
255 if( xObjStg.Is() )
257 uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode&>(rOLENode).GetOLEObj().GetOleRef());
258 if( xObj.is() )
260 embed::XEmbeddedObject *pObj = xObj.get();
261 sal_uInt32 nPictureId = (sal_uInt32)(sal_uIntPtr)pObj;
262 Set_UInt32(pDataAdr, nPictureId);
264 WW8OleMap *pMap = new WW8OleMap(nPictureId);
265 bool bDuplicate = false;
266 WW8OleMaps &rOleMap = GetOLEMap();
267 USHORT nPos;
268 if ( rOleMap.Seek_Entry(pMap, &nPos) )
270 bDuplicate = true;
271 delete pMap;
273 else if( 0 == rOleMap.Insert( pMap) )
274 delete pMap;
276 String sStorageName( '_' );
277 sStorageName += String::CreateFromInt32( nPictureId );
278 SvStorageRef xOleStg = xObjStg->OpenSotStorage( sStorageName,
279 STREAM_READWRITE| STREAM_SHARE_DENYALL );
280 if( xOleStg.Is() )
283 If this object storage has been written already don't
284 waste time rewriting it
286 if (!bDuplicate)
288 sal_Int64 nAspect = rOLENode.GetAspect();
289 svt::EmbeddedObjectRef aObjRef( xObj, nAspect );
290 GetOLEExp().ExportOLEObject( aObjRef, *xOleStg );
291 if ( nAspect == embed::Aspects::MSOLE_ICON )
293 ::rtl::OUString aObjInfo( RTL_CONSTASCII_USTRINGPARAM( "\3ObjInfo" ) );
294 if ( !xOleStg->IsStream( aObjInfo ) )
296 const BYTE pObjInfoData[] = { 0x40, 0x00, 0x03, 0x00 };
297 SvStorageStreamRef rObjInfoStream = xOleStg->OpenSotStream( aObjInfo );
298 if ( rObjInfoStream.Is() && !rObjInfoStream->GetError() )
300 rObjInfoStream->Write( pObjInfoData, sizeof( pObjInfoData ) );
301 xOleStg->Commit();
307 // write as embedded field - the other things will be done
308 // in the escher export
309 String sServer(FieldString(ww::eEMBED));
310 sServer += xOleStg->GetUserName();
311 sServer += ' ';
313 OutputField(0, ww::eEMBED, sServer, WRITEFIELD_START |
314 WRITEFIELD_CMD_START | WRITEFIELD_CMD_END);
316 pChpPlc->AppendFkpEntry( Strm().Tell(),
317 nSize, pSpecOLE );
319 bool bEndCR = true;
321 In the word filter we only need a preview image for
322 floating images, and then only (the usual case) if the
323 object doesn't contain enough information to reconstruct
324 what we need.
326 We don't need a graphic for inline objects, so we don't
327 even need the overhead of a graphic in that case.
329 bool bGraphicNeeded = false;
331 if (mpParentFrame)
333 bGraphicNeeded = true;
335 if (mpParentFrame->IsInline())
337 const SwAttrSet& rSet =
338 mpParentFrame->GetFrmFmt().GetAttrSet();
339 bEndCR = false;
340 bGraphicNeeded = TestOleNeedsGraphic(rSet,
341 xOleStg, xObjStg, sStorageName, const_cast<SwOLENode*>(&rOLENode));
345 if (!bGraphicNeeded)
346 WriteChar(0x1);
347 else
350 ##897##
351 We need to insert the graphic representation of
352 this object for the inline case, otherwise word
353 has no place to find the dimensions of the ole
354 object, and will not be able to draw it
356 OutGrf(*mpParentFrame);
359 OutputField(0, ww::eEMBED, aEmptyStr,
360 WRITEFIELD_END | WRITEFIELD_CLOSE);
362 if (bEndCR) //No newline in inline case
363 WriteCR();
369 void WW8Export::OutGrf(const sw::Frame &rFrame)
371 // GrfNode fuer spaeteres rausschreiben der Grafik merken
372 pGrf->Insert(rFrame);
374 pChpPlc->AppendFkpEntry( Strm().Tell(), pO->Count(), pO->GetData() );
375 pO->Remove( 0, pO->Count() ); // leeren
377 // --> OD 2007-06-06 #i29408#
378 // linked, as-character anchored graphics have to be exported as fields.
379 const SwGrfNode* pGrfNd = rFrame.IsInline() && rFrame.GetContent()
380 ? rFrame.GetContent()->GetGrfNode() : 0;
381 if ( pGrfNd && pGrfNd->IsLinkedFile() )
383 String sStr( FieldString(ww::eINCLUDEPICTURE) );
384 sStr.APPEND_CONST_ASC(" \"");
386 if ( pGrfNd )
388 String aFileURL;
389 pGrfNd->GetFileFilterNms( &aFileURL, 0 );
390 sStr += aFileURL;
393 sStr.APPEND_CONST_ASC("\" \\d");
395 OutputField( 0, ww::eINCLUDEPICTURE, sStr,
396 WRITEFIELD_START | WRITEFIELD_CMD_START | WRITEFIELD_CMD_END );
398 // <--
400 WriteChar( (char)1 ); // Grafik-Sonderzeichen in Haupttext einfuegen
402 BYTE aArr[ 18 ];
403 BYTE* pArr = aArr;
405 const SwFrmFmt &rFlyFmt = rFrame.GetFrmFmt();
406 const RndStdIds eAn = rFlyFmt.GetAttrSet().GetAnchor(false).GetAnchorId();
407 if( eAn == FLY_IN_CNTNT )
409 sal_Int16 eVert = rFlyFmt.GetVertOrient().GetVertOrient();
410 if ((eVert == text::VertOrientation::CHAR_CENTER) || (eVert == text::VertOrientation::LINE_CENTER))
412 bool bVert = false;
413 //The default for word in vertical text mode is to center,
414 //otherwise a sub/super script hack is employed
415 if (pOutFmtNode && pOutFmtNode->ISA(SwCntntNode) )
417 const SwTxtNode* pTxtNd = (const SwTxtNode*)pOutFmtNode;
418 SwPosition aPos(*pTxtNd);
419 bVert = pDoc->IsInVerticalText(aPos) ? true : false;
421 if (!bVert)
423 SwTwips nHeight = rFlyFmt.GetFrmSize().GetHeight();
424 nHeight/=20; //nHeight was in twips, want it in half points, but
425 //then half of total height.
426 long nFontHeight = ((const SvxFontHeightItem&)
427 GetItem(RES_CHRATR_FONTSIZE)).GetHeight();
428 nHeight-=nFontHeight/20;
430 if (bWrtWW8)
431 Set_UInt16( pArr, NS_sprm::LN_CHpsPos );
432 else
433 Set_UInt8( pArr, 101 );
434 Set_UInt16( pArr, -((INT16)nHeight));
439 // sprmCFSpec
440 if( bWrtWW8 )
441 Set_UInt16( pArr, 0x855 );
442 else
443 Set_UInt8( pArr, 117 );
444 Set_UInt8( pArr, 1 );
446 // sprmCPicLocation
447 if( bWrtWW8 )
448 Set_UInt16( pArr, NS_sprm::LN_CPicLocation );
449 else
451 Set_UInt8( pArr, 68 );
452 Set_UInt8( pArr, 4 );
454 Set_UInt32( pArr, GRF_MAGIC_321 );
456 // Magic variieren, damit verschiedene Grafik-Attribute nicht
457 // gemerged werden
458 static BYTE nAttrMagicIdx = 0;
459 --pArr;
460 Set_UInt8( pArr, nAttrMagicIdx++ );
461 pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr );
463 // --> OD 2007-04-23 #i75464#
464 // Check, if graphic isn't exported as-character anchored.
465 // Otherwise, an additional paragraph is exported for a graphic, which is
466 // forced to be treated as inline, because it's anchored inside another frame.
467 if ( !rFrame.IsInline() &&
468 ( ( eAn == FLY_AT_CNTNT && ( bWrtWW8 || !bIsInTable ) ) ||
469 eAn == FLY_PAGE ) )
470 // <--
472 WriteChar( (char)0x0d ); // umgebenden Rahmen mit CR abschliessen
474 static BYTE __READONLY_DATA nSty[2] = { 0, 0 };
475 pO->Insert( nSty, 2, pO->Count() ); // Style #0
476 bool bOldGrf = bOutGrf;
477 bOutGrf = true;
479 OutputFormat( rFrame.GetFrmFmt(), false, false, true ); // Fly-Attrs
481 bOutGrf = bOldGrf;
482 pPapPlc->AppendFkpEntry( Strm().Tell(), pO->Count(), pO->GetData() );
483 pO->Remove( 0, pO->Count() ); // leeren
485 // --> OD 2007-06-06 #i29408#
486 // linked, as-character anchored graphics have to be exported as fields.
487 else if ( pGrfNd && pGrfNd->IsLinkedFile() )
489 OutputField( 0, ww::eINCLUDEPICTURE, String(), WRITEFIELD_CLOSE );
491 // <--
494 GraphicDetails& GraphicDetails::operator=(const GraphicDetails &rOther)
496 maFly = rOther.maFly;
497 mnPos = rOther.mnPos;
498 mnWid = rOther.mnWid;
499 mnHei = rOther.mnHei;
500 return *this;
503 void SwWW8WrGrf::Insert(const sw::Frame &rFly)
505 const Size aSize( rFly.GetLayoutSize() );
506 const UINT16 nWidth = static_cast< UINT16 >(aSize.Width());
507 const UINT16 nHeight = static_cast< UINT16 >(aSize.Height());
508 maDetails.push_back(GraphicDetails(rFly, nWidth, nHeight));
511 void SwWW8WrGrf::WritePICFHeader(SvStream& rStrm, const sw::Frame &rFly,
512 UINT16 mm, UINT16 nWidth, UINT16 nHeight, const SwAttrSet* pAttrSet)
514 INT16 nXSizeAdd = 0, nYSizeAdd = 0;
515 INT16 nCropL = 0, nCropR = 0, nCropT = 0, nCropB = 0;
517 // Crop-AttributInhalt in Header schreiben ( falls vorhanden )
518 const SfxPoolItem* pItem;
519 if (pAttrSet && (SFX_ITEM_ON
520 == pAttrSet->GetItemState(RES_GRFATR_CROPGRF, false, &pItem)))
522 const SwCropGrf& rCr = *(SwCropGrf*)pItem;
523 nCropL = (INT16)rCr.GetLeft();
524 nCropR = (INT16)rCr.GetRight();
525 nCropT = (INT16)rCr.GetTop();
526 nCropB = (INT16)rCr.GetBottom();
527 nXSizeAdd = nXSizeAdd - (INT16)( rCr.GetLeft() + rCr.GetRight() );
528 nYSizeAdd = nYSizeAdd - (INT16)( rCr.GetTop() + rCr.GetBottom() );
531 Size aGrTwipSz(rFly.GetSize());
532 bool bWrtWW8 = rWrt.bWrtWW8;
533 UINT16 nHdrLen = bWrtWW8 ? 0x44 : 0x3A;
535 BYTE aArr[ 0x44 ] = { 0 };
537 BYTE* pArr = aArr + 0x2E; //Do borders first
539 const SwAttrSet& rAttrSet = rFly.GetFrmFmt().GetAttrSet();
540 if (SFX_ITEM_ON == rAttrSet.GetItemState(RES_BOX, false, &pItem))
542 const SvxBoxItem* pBox = (const SvxBoxItem*)pItem;
543 if( pBox )
545 bool bShadow = false; // Shadow ?
546 const SvxShadowItem* pSI =
547 sw::util::HasItem<SvxShadowItem>(rAttrSet, RES_SHADOW);
548 if (pSI)
550 bShadow = (pSI->GetLocation() != SVX_SHADOW_NONE) &&
551 (pSI->GetWidth() != 0);
554 BYTE aLnArr[4] = { BOX_LINE_TOP, BOX_LINE_LEFT,
555 BOX_LINE_BOTTOM, BOX_LINE_RIGHT };
556 for( BYTE i = 0; i < 4; ++i )
558 const SvxBorderLine* pLn = pBox->GetLine( aLnArr[ i ] );
559 WW8_BRC aBrc;
560 if (pLn)
562 aBrc = rWrt.TranslateBorderLine( *pLn,
563 pBox->GetDistance( aLnArr[ i ] ), bShadow );
566 //use importer logic to determine how large the exported
567 //border will really be in word and adjust accordingly
568 short nSpacing;
569 short nThick = aBrc.DetermineBorderProperties(!bWrtWW8,
570 &nSpacing);
571 switch (aLnArr[ i ])
573 case BOX_LINE_TOP:
574 case BOX_LINE_BOTTOM:
575 nHeight -= bShadow ? nThick*2 : nThick;
576 nHeight = nHeight - nSpacing;
577 break;
578 case BOX_LINE_LEFT:
579 case BOX_LINE_RIGHT:
580 default:
581 nWidth -= bShadow ? nThick*2 : nThick;
582 nWidth = nWidth - nSpacing;
583 break;
585 memcpy( pArr, &aBrc.aBits1, 2);
586 pArr+=2;
588 if( bWrtWW8 )
590 memcpy( pArr, &aBrc.aBits2, 2);
591 pArr+=2;
597 pArr = aArr + 4; //skip lcb
598 Set_UInt16( pArr, nHdrLen ); // set cbHeader
600 Set_UInt16( pArr, mm ); // set mm
603 #92494#
604 Just in case our original size is too big to fit inside a ushort we can
605 substitute the final size and loose on retaining the scaling factor but
606 still keep the correct display size anyway.
608 if ( (aGrTwipSz.Width() > USHRT_MAX) || (aGrTwipSz.Height() > USHRT_MAX)
609 || (aGrTwipSz.Width() < 0 ) || (aGrTwipSz.Height() < 0) )
611 aGrTwipSz.Width() = nWidth;
612 aGrTwipSz.Height() = nHeight;
614 using namespace sw::types;
615 // set xExt & yExt
616 Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Width() * 254L / 144));
617 Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Height() * 254L / 144));
618 pArr += 16;
619 // skip hMF & rcWinMF
620 // set dxaGoal & dyaGoal
621 Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Width()));
622 Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Height()));
624 if( aGrTwipSz.Width() + nXSizeAdd ) // set mx
626 double fVal = nWidth * 1000.0 / (aGrTwipSz.Width() + nXSizeAdd);
627 Set_UInt16( pArr, (USHORT)::rtl::math::round(fVal) );
629 else
630 pArr += 2;
632 if( aGrTwipSz.Height() + nYSizeAdd ) // set my
634 double fVal = nHeight * 1000.0 / (aGrTwipSz.Height() + nYSizeAdd);
635 Set_UInt16( pArr, (USHORT)::rtl::math::round(fVal) );
637 else
638 pArr += 2;
640 Set_UInt16( pArr, nCropL ); // set dxaCropLeft
641 Set_UInt16( pArr, nCropT ); // set dyaCropTop
642 Set_UInt16( pArr, nCropR ); // set dxaCropRight
643 Set_UInt16( pArr, nCropB ); // set dyaCropBottom
645 rStrm.Write( aArr, nHdrLen );
648 void SwWW8WrGrf::WriteGrfFromGrfNode(SvStream& rStrm, const SwGrfNode &rGrfNd,
649 const sw::Frame &rFly, UINT16 nWidth, UINT16 nHeight)
651 if (rGrfNd.IsLinkedFile()) // Linked File
653 String aFileN;
654 rGrfNd.GetFileFilterNms( &aFileN, 0 );
656 // --> OD 2007-06-06 #i29408# - take the file URL as it is.
657 // aFileN = URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(),
658 // aFileN);
659 // INetURLObject aUrl( aFileN );
660 // if( aUrl.GetProtocol() == INET_PROT_FILE )
661 // aFileN = aUrl.PathToFileName();
662 // <--
664 //JP 05.12.98: nach einigen tests hat sich gezeigt, das WW mit 99 nicht
665 // klarkommt. Sie selbst schreiben aber bei Verknuepfunfen,
666 // egal um welchen Type es sich handelt, immer den Wert 94.
667 // Bug 59859
668 // if ( COMPARE_EQUAL == aFiltN.ICompare( "TIF", 3 ) )
669 // mm = 99; // 99 = TIFF
670 // else
671 UINT16 mm = 94; // 94 = BMP, GIF
673 WritePICFHeader(rStrm, rFly, mm, nWidth, nHeight,
674 rGrfNd.GetpSwAttrSet());
675 rStrm << (BYTE)aFileN.Len(); // Pascal-String schreiben
676 SwWW8Writer::WriteString8(rStrm, aFileN, false,
677 RTL_TEXTENCODING_MS_1252);
679 else // Embedded File oder DDE oder so was
681 if (rWrt.bWrtWW8)
683 WritePICFHeader(rStrm, rFly, 0x64, nWidth, nHeight,
684 rGrfNd.GetpSwAttrSet());
685 SwBasicEscherEx aInlineEscher(&rStrm, rWrt);
686 aInlineEscher.WriteGrfFlyFrame(rFly.GetFrmFmt(), 0x401);
687 aInlineEscher.WritePictures();
689 else
691 Graphic& rGrf = const_cast<Graphic&>(rGrfNd.GetGrf());
692 bool bSwapped = rGrf.IsSwapOut() ? true : false;
693 // immer ueber den Node einswappen!
694 const_cast<SwGrfNode&>(rGrfNd).SwapIn();
696 GDIMetaFile aMeta;
697 switch (rGrf.GetType())
699 case GRAPHIC_BITMAP: // Bitmap -> in Metafile abspielen
701 VirtualDevice aVirt;
702 aMeta.Record(&aVirt);
703 aVirt.DrawBitmap( Point( 0,0 ), rGrf.GetBitmap() );
704 aMeta.Stop();
705 aMeta.WindStart();
706 aMeta.SetPrefMapMode( rGrf.GetPrefMapMode());
707 aMeta.SetPrefSize( rGrf.GetPrefSize());
709 break;
710 case GRAPHIC_GDIMETAFILE : // GDI ( =SV ) Metafile
711 aMeta = rGrf.GetGDIMetaFile();
712 break;
713 default:
714 return;
717 WritePICFHeader(rStrm, rFly, 8, nWidth, nHeight,
718 rGrfNd.GetpSwAttrSet());
719 WriteWindowMetafileBits(rStrm, aMeta);
721 if (bSwapped)
722 rGrf.SwapOut();
727 void SwWW8WrGrf::WriteGraphicNode(SvStream& rStrm, const GraphicDetails &rItem)
729 UINT16 nWidth = rItem.mnWid;
730 UINT16 nHeight = rItem.mnHei;
731 UINT32 nPos = rStrm.Tell(); // Grafik-Anfang merken
733 const sw::Frame &rFly = rItem.maFly;
734 switch (rFly.GetWriterType())
736 case sw::Frame::eGraphic:
738 const SwNode *pNode = rItem.maFly.GetContent();
739 const SwGrfNode *pNd = pNode ? pNode->GetGrfNode() : 0;
740 ASSERT(pNd, "Impossible");
741 if (pNd)
742 WriteGrfFromGrfNode(rStrm, *pNd, rItem.maFly, nWidth, nHeight);
744 break;
745 case sw::Frame::eOle:
747 #ifdef OLE_PREVIEW_AS_EMF
748 const SwNode *pNode = rItem.maFly.GetContent();
749 const SwOLENode *pNd = pNode ? pNode->GetOLENode() : 0;
750 ASSERT(pNd, "Impossible");
751 if (!rWrt.bWrtWW8)
753 SwOLENode *pOleNd = const_cast<SwOLENode*>(pNd);
754 ASSERT( pOleNd, " Wer hat den OleNode versteckt ?" );
755 SwOLEObj& rSObj= pOleNd->GetOLEObj();
756 uno::Reference < embed::XEmbeddedObject > rObj( rSObj.GetOleRef() );
758 comphelper::EmbeddedObjectContainer aCnt( pOleNd->GetDoc()->GetDocStorage() );
760 SvStream* pGraphicStream = ::utl::UcbStreamHelper::CreateStream( aCnt.GetGraphicStream( rObj ) );
761 DBG_ASSERT( pGraphicStream && !pGraphicStream->GetError(), "No graphic stream available!" );
762 if ( pGraphicStream && !pGraphicStream->GetError() )
764 Graphic aGr;
765 GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
766 if( pGF->ImportGraphic( aGr, aEmptyStr, *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ) == GRFILTER_OK )
768 //TODO/LATER: do we really want to use GDIMetafile?!
769 GDIMetaFile aMtf;
770 aMtf = aGr.GetGDIMetaFile();
771 aMtf.WindStart();
772 aMtf.Play(Application::GetDefaultDevice(), Point(0, 0),
773 Size(2880, 2880));
774 WritePICFHeader(rStrm, rFly, 8, nWidth, nHeight,
775 pNd->GetpSwAttrSet());
776 WriteWindowMetafileBits(rStrm, aMtf);
779 else
780 delete pGraphicStream;
782 else
784 //Convert this ole2 preview in ww8+ to an EMF for better unicode
785 //support (note that at this moment this breaks StarSymbol
786 //using graphics because I need to embed starsymbol in exported
787 //documents.
788 WritePICFHeader(rStrm, rFly, 0x64, nWidth, nHeight,
789 pNd->GetpSwAttrSet());
790 SwBasicEscherEx aInlineEscher(&rStrm, rWrt);
791 aInlineEscher.WriteOLEFlyFrame(rFly.GetFrmFmt(), 0x401);
792 aInlineEscher.WritePictures();
794 #else
795 // cast away const
796 SwOLENode *pOleNd = const_cast<SwOLENode*>(pNd);
797 ASSERT( pOleNd, " Wer hat den OleNode versteckt ?" );
798 SwOLEObj& rSObj= pOleNd->GetOLEObj();
800 // TODO/LATER: do we need to load object?
801 Graphic* pGr = SdrOle2Obj::GetGraphicFromObject( pOleNd->GetDoc()->GetDocStorage(), rObj );
803 //TODO/LATER: do we really want to use GDIMetafile?!
804 GDIMetaFile aMtf;
805 if ( pGr )
806 aMtf = pGr->GetGDIMetaFile();
808 Size aS(aMtf.GetPrefSize());
809 aMtf.WindStart();
810 aMtf.Play(Application::GetDefaultDevice(), Point(0, 0),
811 Size(2880, 2880));
813 WritePICFHeader(rStrm, rFly, 8, nWidth, nHeight,
814 pNd->GetpSwAttrSet());
815 WriteWindowMetafileBits(rStrm, aMtf);
816 delete pGr;
817 #endif
819 break;
820 case sw::Frame::eDrawing:
821 case sw::Frame::eTxtBox:
822 case sw::Frame::eFormControl:
823 ASSERT(rWrt.bWrtWW8,
824 "You can't try and export these in WW8 format, a filter bug");
826 #i3958# We only export an empty dummy picture frame here, this is
827 what word does the escher export should contain an anchored to
828 character element which is drawn over this dummy and the whole
829 shebang surrounded with a SHAPE field. This isn't *my* hack :-),
830 its what word does.
832 if (rWrt.bWrtWW8)
834 WritePICFHeader(rStrm, rFly, 0x64, nWidth, nHeight);
835 SwBasicEscherEx aInlineEscher(&rStrm, rWrt);
836 aInlineEscher.WriteEmptyFlyFrame(rFly.GetFrmFmt(), 0x401);
838 break;
839 default:
840 ASSERT(!this,
841 "Some inline export not implemented, remind cmc before we ship :-)");
842 break;
845 UINT32 nPos2 = rStrm.Tell(); // Ende merken
846 rStrm.Seek( nPos );
847 SVBT32 nLen;
848 UInt32ToSVBT32( nPos2 - nPos, nLen ); // Grafik-Laenge ausrechnen
849 rStrm.Write( nLen, 4 ); // im Header einpatchen
850 rStrm.Seek( nPos2 ); // Pos wiederherstellen
853 // SwWW8WrGrf::Write() wird nach dem Text gerufen. Es schreibt die alle
854 // Grafiken raus und merkt sich die File-Positionen der Grafiken, damit
855 // beim Schreiben der Attribute die Positionen in die PicLocFc-Sprms
856 // eingepatcht werden koennen.
857 // Das Suchen in den Attributen nach dem Magic ULONG und das Patchen
858 // passiert beim Schreiben der Attribute. Die SwWW8WrGrf-Klasse liefert
859 // hierfuer nur mit GetFPos() sequentiell die Positionen.
860 void SwWW8WrGrf::Write()
862 SvStream& rStrm = *rWrt.pDataStrm;
863 myiter aEnd = maDetails.end();
864 for (myiter aIter = maDetails.begin(); aIter != aEnd; ++aIter)
866 UINT32 nPos = rStrm.Tell(); // auf 4 Bytes alignen
867 if( nPos & 0x3 )
868 SwWW8Writer::FillCount( rStrm, 4 - ( nPos & 0x3 ) );
870 bool bDuplicated = false;
871 for (myiter aIter2 = maDetails.begin(); aIter2 != aIter; ++aIter2)
873 if (*aIter2 == *aIter)
875 aIter->mnPos = aIter2->mnPos;
876 bDuplicated = true;
877 break;
881 if (!bDuplicated)
883 aIter->mnPos = rStrm.Tell();
884 WriteGraphicNode(rStrm, *aIter);
889 /* vi:set tabstop=4 shiftwidth=4 expandtab: */