1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: wrtww8gr.cxx,v $
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>
61 #include <frmfmt.hxx> // class SwFlyFrmFmt
62 #include <grfatr.hxx> // class SwCropGrf
65 #include <fmtfsize.hxx>
66 #include <fmtornt.hxx>
68 #include <writerfilter/doctok/sprmids.hxx>
71 #include "writerhelper.hxx"
72 #include "writerwordglue.hxx"
73 #include "ww8struc.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 !!
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" );
103 ASSERT( mpParentFrame
, "frame not set!" );
106 OutGrf( *mpParentFrame
);
111 bool WW8Export::TestOleNeedsGraphic(const SwAttrSet
& rSet
,
112 SvStorageRef xOleStg
, SvStorageRef xObjStg
, String
&rStorageName
,
115 #ifdef NO_OLE_SIZE_OPTIMIZE
118 bool bGraphicNeeded
= false;
119 SfxItemIter
aIter( rSet
);
120 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
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.
136 case RES_VERT_ORIENT
:
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
152 if (!bGraphicNeeded
&& SwWW8ImplReader::ImportOleWMF(xOleStg
,aWMF
,nX
,nY
))
154 // bGraphicNeeded set to true is right / fixes #i51670#.
155 bGraphicNeeded
= true;
157 Rectangle
aRect( aTmpPoint
, Size( nX
, nY
) );
158 Graphic
aGraph(aWMF
);
160 ErrCode nErr
= ERRCODE_NONE
;
162 sal_Int64 nAspect
= embed::Aspects::MSOLE_CONTENT
;
164 nAspect
= pOLENd
->GetAspect();
165 SdrOle2Obj
*pRet
= SvxMSDffManager::CreateSdrOLEFromStorage(
166 rStorageName
,xObjStg
,pDoc
->GetDocStorage(),aGraph
,aRect
,aVisArea
,0,nErr
,0,nAspect
);
170 uno::Reference
< embed::XEmbeddedObject
> xObj
= pOLENd
->GetOLEObj().GetOleRef();
173 SvStream
* pGraphicStream
= NULL
;
174 comphelper::EmbeddedObjectContainer
aCnt( pDoc
->GetDocStorage() );
177 uno::Reference
< embed::XEmbedPersist
> xPersist(
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
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() )
193 GraphicFilter
* pGF
= GraphicFilter::GetGraphicFilter();
194 if( pGF
->ImportGraphic( aGr1
, aEmptyStr
, *pGraphicStream
, GRFILTER_FORMAT_DONTKNOW
) == GRFILTER_OK
)
197 delete pGraphicStream
;
199 ::utl::UcbStreamHelper::CreateStream( aCnt
.GetGraphicStream( pRet
->GetObjRef() ) );
200 if( pGF
->ImportGraphic( aGr2
, aEmptyStr
, *pGraphicStream
, GRFILTER_FORMAT_DONTKNOW
) == GRFILTER_OK
)
203 bGraphicNeeded
= false;
208 delete pGraphicStream
;
215 bGraphicNeeded
= true;
216 return bGraphicNeeded
;
220 void WW8Export::OutputOLENode( const SwOLENode
& rOLENode
)
222 #if OSL_DEBUG_LEVEL > 0
223 fprintf( stderr
, "WW8Export::OutputOLENode( const SwOLENode& rOLENode )\n" );
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)
241 pSpecOLE
= aSpecOLE_WW8
;
242 nSize
= sizeof( aSpecOLE_WW8
);
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
);
257 uno::Reference
< embed::XEmbeddedObject
> xObj(const_cast<SwOLENode
&>(rOLENode
).GetOLEObj().GetOleRef());
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();
268 if ( rOleMap
.Seek_Entry(pMap
, &nPos
) )
273 else if( 0 == rOleMap
.Insert( pMap
) )
276 String
sStorageName( '_' );
277 sStorageName
+= String::CreateFromInt32( nPictureId
);
278 SvStorageRef xOleStg
= xObjStg
->OpenSotStorage( sStorageName
,
279 STREAM_READWRITE
| STREAM_SHARE_DENYALL
);
283 If this object storage has been written already don't
284 waste time rewriting it
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
) );
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();
313 OutputField(0, ww::eEMBED
, sServer
, WRITEFIELD_START
|
314 WRITEFIELD_CMD_START
| WRITEFIELD_CMD_END
);
316 pChpPlc
->AppendFkpEntry( Strm().Tell(),
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
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;
333 bGraphicNeeded
= true;
335 if (mpParentFrame
->IsInline())
337 const SwAttrSet
& rSet
=
338 mpParentFrame
->GetFrmFmt().GetAttrSet();
340 bGraphicNeeded
= TestOleNeedsGraphic(rSet
,
341 xOleStg
, xObjStg
, sStorageName
, const_cast<SwOLENode
*>(&rOLENode
));
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
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(" \"");
389 pGrfNd
->GetFileFilterNms( &aFileURL
, 0 );
393 sStr
.APPEND_CONST_ASC("\" \\d");
395 OutputField( 0, ww::eINCLUDEPICTURE
, sStr
,
396 WRITEFIELD_START
| WRITEFIELD_CMD_START
| WRITEFIELD_CMD_END
);
400 WriteChar( (char)1 ); // Grafik-Sonderzeichen in Haupttext einfuegen
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
))
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;
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;
431 Set_UInt16( pArr
, NS_sprm::LN_CHpsPos
);
433 Set_UInt8( pArr
, 101 );
434 Set_UInt16( pArr
, -((INT16
)nHeight
));
441 Set_UInt16( pArr
, 0x855 );
443 Set_UInt8( pArr
, 117 );
444 Set_UInt8( pArr
, 1 );
448 Set_UInt16( pArr
, NS_sprm::LN_CPicLocation
);
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
458 static BYTE nAttrMagicIdx
= 0;
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
) ) ||
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
;
479 OutputFormat( rFrame
.GetFrmFmt(), false, false, true ); // Fly-Attrs
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
);
494 GraphicDetails
& GraphicDetails::operator=(const GraphicDetails
&rOther
)
496 maFly
= rOther
.maFly
;
497 mnPos
= rOther
.mnPos
;
498 mnWid
= rOther
.mnWid
;
499 mnHei
= rOther
.mnHei
;
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
;
545 bool bShadow
= false; // Shadow ?
546 const SvxShadowItem
* pSI
=
547 sw::util::HasItem
<SvxShadowItem
>(rAttrSet
, RES_SHADOW
);
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
] );
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
569 short nThick
= aBrc
.DetermineBorderProperties(!bWrtWW8
,
574 case BOX_LINE_BOTTOM
:
575 nHeight
-= bShadow
? nThick
*2 : nThick
;
576 nHeight
= nHeight
- nSpacing
;
581 nWidth
-= bShadow
? nThick
*2 : nThick
;
582 nWidth
= nWidth
- nSpacing
;
585 memcpy( pArr
, &aBrc
.aBits1
, 2);
590 memcpy( pArr
, &aBrc
.aBits2
, 2);
597 pArr
= aArr
+ 4; //skip lcb
598 Set_UInt16( pArr
, nHdrLen
); // set cbHeader
600 Set_UInt16( pArr
, mm
); // set mm
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
;
616 Set_UInt16(pArr
, msword_cast
<sal_uInt16
>(aGrTwipSz
.Width() * 254L / 144));
617 Set_UInt16(pArr
, msword_cast
<sal_uInt16
>(aGrTwipSz
.Height() * 254L / 144));
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
) );
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
) );
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
654 rGrfNd
.GetFileFilterNms( &aFileN
, 0 );
656 // --> OD 2007-06-06 #i29408# - take the file URL as it is.
657 // aFileN = URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(),
659 // INetURLObject aUrl( aFileN );
660 // if( aUrl.GetProtocol() == INET_PROT_FILE )
661 // aFileN = aUrl.PathToFileName();
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.
668 // if ( COMPARE_EQUAL == aFiltN.ICompare( "TIF", 3 ) )
669 // mm = 99; // 99 = TIFF
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
683 WritePICFHeader(rStrm
, rFly
, 0x64, nWidth
, nHeight
,
684 rGrfNd
.GetpSwAttrSet());
685 SwBasicEscherEx
aInlineEscher(&rStrm
, rWrt
);
686 aInlineEscher
.WriteGrfFlyFrame(rFly
.GetFrmFmt(), 0x401);
687 aInlineEscher
.WritePictures();
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();
697 switch (rGrf
.GetType())
699 case GRAPHIC_BITMAP
: // Bitmap -> in Metafile abspielen
702 aMeta
.Record(&aVirt
);
703 aVirt
.DrawBitmap( Point( 0,0 ), rGrf
.GetBitmap() );
706 aMeta
.SetPrefMapMode( rGrf
.GetPrefMapMode());
707 aMeta
.SetPrefSize( rGrf
.GetPrefSize());
710 case GRAPHIC_GDIMETAFILE
: // GDI ( =SV ) Metafile
711 aMeta
= rGrf
.GetGDIMetaFile();
717 WritePICFHeader(rStrm
, rFly
, 8, nWidth
, nHeight
,
718 rGrfNd
.GetpSwAttrSet());
719 WriteWindowMetafileBits(rStrm
, aMeta
);
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");
742 WriteGrfFromGrfNode(rStrm
, *pNd
, rItem
.maFly
, nWidth
, nHeight
);
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");
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() )
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?!
770 aMtf
= aGr
.GetGDIMetaFile();
772 aMtf
.Play(Application::GetDefaultDevice(), Point(0, 0),
774 WritePICFHeader(rStrm
, rFly
, 8, nWidth
, nHeight
,
775 pNd
->GetpSwAttrSet());
776 WriteWindowMetafileBits(rStrm
, aMtf
);
780 delete pGraphicStream
;
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
788 WritePICFHeader(rStrm
, rFly
, 0x64, nWidth
, nHeight
,
789 pNd
->GetpSwAttrSet());
790 SwBasicEscherEx
aInlineEscher(&rStrm
, rWrt
);
791 aInlineEscher
.WriteOLEFlyFrame(rFly
.GetFrmFmt(), 0x401);
792 aInlineEscher
.WritePictures();
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?!
806 aMtf
= pGr
->GetGDIMetaFile();
808 Size
aS(aMtf
.GetPrefSize());
810 aMtf
.Play(Application::GetDefaultDevice(), Point(0, 0),
813 WritePICFHeader(rStrm
, rFly
, 8, nWidth
, nHeight
,
814 pNd
->GetpSwAttrSet());
815 WriteWindowMetafileBits(rStrm
, aMtf
);
820 case sw::Frame::eDrawing
:
821 case sw::Frame::eTxtBox
:
822 case sw::Frame::eFormControl
:
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 :-),
834 WritePICFHeader(rStrm
, rFly
, 0x64, nWidth
, nHeight
);
835 SwBasicEscherEx
aInlineEscher(&rStrm
, rWrt
);
836 aInlineEscher
.WriteEmptyFlyFrame(rFly
.GetFrmFmt(), 0x401);
841 "Some inline export not implemented, remind cmc before we ship :-)");
845 UINT32 nPos2
= rStrm
.Tell(); // Ende merken
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
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
;
883 aIter
->mnPos
= rStrm
.Tell();
884 WriteGraphicNode(rStrm
, *aIter
);
889 /* vi:set tabstop=4 shiftwidth=4 expandtab: */