1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <com/sun/star/embed/XEmbedPersist.hpp>
22 #include <com/sun/star/embed/Aspects.hpp>
23 #include <com/sun/star/embed/ElementModes.hpp>
24 #include <rtl/math.hxx>
25 #include <vcl/graphicfilter.hxx>
26 #include <vcl/wmf.hxx>
27 #include <svl/itemiter.hxx>
28 #include "svl/urihelper.hxx"
30 #include <svtools/embedhlp.hxx>
32 #include <vcl/virdev.hxx>
33 #include <vcl/svapp.hxx>
35 #include <hintids.hxx>
36 #include <editeng/boxitem.hxx>
37 #include <editeng/shaditem.hxx>
38 #include <filter/msfilter/msoleexp.hxx>
39 #include <editeng/lrspitem.hxx> // SvxLRSpaceItem
40 #include <editeng/ulspitem.hxx>
41 #include <editeng/fhgtitem.hxx>
42 #include <svx/svdoole2.hxx>
44 #include <unotools/ucbstreamhelper.hxx>
45 #include <fmtanchr.hxx>
47 #include <frmfmt.hxx> // class SwFlyFrmFmt
48 #include <grfatr.hxx> // class SwCropGrf
51 #include <fmtfsize.hxx>
52 #include <fmtornt.hxx>
54 #include <doctok/sprmids.hxx>
57 #include "writerhelper.hxx"
58 #include "writerwordglue.hxx"
59 #include "ww8struc.hxx"
64 #include "ww8attributeoutput.hxx"
70 #if OSL_DEBUG_LEVEL > 1
74 using namespace ::com::sun::star
;
75 using namespace nsFieldFlags
;
78 // 5. convert the MapModes that Widows can't handle
80 // OutGrf () is called for every GrafNode in the document. Es wird ein PicLocFc-Sprm
81 // eingefuegt, der statt Adresse ein Magic sal_uLong enthaelt. Ausserdem wird
82 // in der Graf-Klasse der GrfNode-Ptr gemerkt ( fuers spaetere Ausgeben der
83 // Grafiken und Patchen der PicLocFc-Attribute )
85 void WW8Export::OutputGrfNode( const SwGrfNode
& /*rNode*/ )
87 OSL_TRACE("WW8Export::OutputGrfNode( const SwGrfNode& )" );
88 OSL_ENSURE( mpParentFrame
, "frame not set!" );
91 OutGrf( *mpParentFrame
);
96 bool WW8Export::TestOleNeedsGraphic(const SwAttrSet
& rSet
,
97 SvStorageRef xOleStg
, SvStorageRef xObjStg
, String
&rStorageName
,
100 bool bGraphicNeeded
= false;
101 SfxItemIter
aIter( rSet
);
102 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
105 switch (pItem
->Which())
108 For an inline object these properties are irrelevent because they
109 will be the same as the defaults that msword applies in their
110 absence, so if that is all that there is for these inline objects
111 then if there turns out to be enough information in the object
112 itself to regenerate the correct size and preview of the object
113 then we will not need to provide an additional graphics preview in
114 the data stream, which can save a lot of disk space.
118 case RES_VERT_ORIENT
:
122 bGraphicNeeded
= true;
124 } while( !bGraphicNeeded
&& !aIter
.IsAtEnd() &&
125 0 != ( pItem
= aIter
.NextItem() ) );
128 Now we must see if the object contains a preview itself which is equal to
129 the preview that we are currently using. If the graphics are equal then we
130 dont need to store another preview
134 if (!bGraphicNeeded
&& SwWW8ImplReader::ImportOleWMF(xOleStg
,aWMF
,nX
,nY
))
136 // bGraphicNeeded set to true is right / fixes #i51670#.
137 bGraphicNeeded
= true;
139 Rectangle
aRect( aTmpPoint
, Size( nX
, nY
) );
140 Graphic
aGraph(aWMF
);
142 ErrCode nErr
= ERRCODE_NONE
;
144 sal_Int64 nAspect
= embed::Aspects::MSOLE_CONTENT
;
146 nAspect
= pOLENd
->GetAspect();
147 SdrOle2Obj
*pRet
= SvxMSDffManager::CreateSdrOLEFromStorage(
148 rStorageName
,xObjStg
,pDoc
->GetDocStorage(),aGraph
,aRect
,aVisArea
,0,nErr
,0,nAspect
);
152 uno::Reference
< embed::XEmbeddedObject
> xObj
= pOLENd
->GetOLEObj().GetOleRef();
155 SvStream
* pGraphicStream
= NULL
;
156 comphelper::EmbeddedObjectContainer
aCnt( pDoc
->GetDocStorage() );
159 uno::Reference
< embed::XEmbedPersist
> xPersist(
161 uno::UNO_QUERY_THROW
);
163 // it makes no sence to search the object in the container by reference since the object was created
164 // outside of the container and was not inserted there, only the name makes sence
166 ::utl::UcbStreamHelper::CreateStream( aCnt
.GetGraphicStream( xPersist
->getEntryName() ) );
168 catch( const uno::Exception
& )
171 OSL_ENSURE( pGraphicStream
&& !pGraphicStream
->GetError(), "No graphic stream available!" );
172 if ( pGraphicStream
&& !pGraphicStream
->GetError() )
175 GraphicFilter
& rGF
= GraphicFilter::GetGraphicFilter();
176 if( rGF
.ImportGraphic( aGr1
, aEmptyStr
, *pGraphicStream
, GRFILTER_FORMAT_DONTKNOW
) == GRFILTER_OK
)
179 delete pGraphicStream
;
181 ::utl::UcbStreamHelper::CreateStream( aCnt
.GetGraphicStream( pRet
->GetObjRef() ) );
182 if( rGF
.ImportGraphic( aGr2
, aEmptyStr
, *pGraphicStream
, GRFILTER_FORMAT_DONTKNOW
) == GRFILTER_OK
)
185 bGraphicNeeded
= false;
190 delete pGraphicStream
;
197 bGraphicNeeded
= true;
198 return bGraphicNeeded
;
201 void WW8Export::OutputOLENode( const SwOLENode
& rOLENode
)
203 OSL_TRACE("WW8Export::OutputOLENode( const SwOLENode& rOLENode )" );
207 static sal_uInt8 aSpecOLE_WW8
[] = {
208 0x03, 0x6a, 0, 0, 0, 0, // sprmCPicLocation
209 0x0a, 0x08, 1, // sprmCFOLE2
210 0x56, 0x08, 1 // sprmCFObj
212 static sal_uInt8 aSpecOLE_WW6
[] = {
213 68, 4, 0, 0, 0, 0, // sprmCPicLocation (len is 4)
220 pSpecOLE
= aSpecOLE_WW8
;
221 nSize
= sizeof( aSpecOLE_WW8
);
225 pSpecOLE
= aSpecOLE_WW6
;
226 nSize
= sizeof( aSpecOLE_WW6
);
228 pDataAdr
= pSpecOLE
+ 2; //WW6 sprm is 1 but has 1 byte len as well.
230 SvStorageRef xObjStg
= GetWriter().GetStorage().OpenSotStorage(
231 OUString(SL::aObjectPool
), STREAM_READWRITE
|
232 STREAM_SHARE_DENYALL
);
236 uno::Reference
< embed::XEmbeddedObject
> xObj(const_cast<SwOLENode
&>(rOLENode
).GetOLEObj().GetOleRef());
239 const embed::XEmbeddedObject
*pObj
= xObj
.get();
240 WW8OleMap
& rPointerToObjId
= GetOLEMap();
241 //Don't want to use pointer ids, as is traditional, because we need
242 //to put this into a 32bit value, and on 64bit the bottom bits
243 //might collide and two unrelated ole objects end up considered the
244 //same. Don't want to simply start at 0 which is a special value
245 sal_Int32 nPictureId
= SAL_MAX_INT32
- rPointerToObjId
.size();
246 WW8OleMap::value_type entry
= std::make_pair(pObj
, nPictureId
);
247 std::pair
<WW8OleMap::iterator
, bool> aRes
= rPointerToObjId
.insert(entry
);
248 bool bIsNotDuplicate
= aRes
.second
; //.second is false when element already existed
249 nPictureId
= aRes
.first
->second
;
250 Set_UInt32(pDataAdr
, nPictureId
);
251 String sStorageName
= OUString('_');
252 sStorageName
+= OUString::number( nPictureId
);
253 SvStorageRef xOleStg
= xObjStg
->OpenSotStorage( sStorageName
,
254 STREAM_READWRITE
| STREAM_SHARE_DENYALL
);
258 If this object storage has been written already don't
259 waste time rewriting it
263 sal_Int64 nAspect
= rOLENode
.GetAspect();
264 svt::EmbeddedObjectRef
aObjRef( xObj
, nAspect
);
265 GetOLEExp().ExportOLEObject( aObjRef
, *xOleStg
);
266 if ( nAspect
== embed::Aspects::MSOLE_ICON
)
268 OUString
aObjInfo( "\3ObjInfo" );
269 if ( !xOleStg
->IsStream( aObjInfo
) )
271 const sal_uInt8 pObjInfoData
[] = { 0x40, 0x00, 0x03, 0x00 };
272 SvStorageStreamRef rObjInfoStream
= xOleStg
->OpenSotStream( aObjInfo
);
273 if ( rObjInfoStream
.Is() && !rObjInfoStream
->GetError() )
275 rObjInfoStream
->Write( pObjInfoData
, sizeof( pObjInfoData
) );
282 // write as embedded field - the other things will be done
283 // in the escher export
284 String
sServer(FieldString(ww::eEMBED
));
285 sServer
+= xOleStg
->GetUserName();
288 OutputField(0, ww::eEMBED
, sServer
, WRITEFIELD_START
|
289 WRITEFIELD_CMD_START
| WRITEFIELD_CMD_END
);
291 pChpPlc
->AppendFkpEntry( Strm().Tell(),
296 In the word filter we only need a preview image for
297 floating images, and then only (the usual case) if the
298 object doesn't contain enough information to reconstruct
301 We don't need a graphic for inline objects, so we don't
302 even need the overhead of a graphic in that case.
304 bool bGraphicNeeded
= false;
308 bGraphicNeeded
= true;
310 if (mpParentFrame
->IsInline())
312 const SwAttrSet
& rSet
=
313 mpParentFrame
->GetFrmFmt().GetAttrSet();
315 bGraphicNeeded
= TestOleNeedsGraphic(rSet
,
316 xOleStg
, xObjStg
, sStorageName
, const_cast<SwOLENode
*>(&rOLENode
));
326 We need to insert the graphic representation of
327 this object for the inline case, otherwise word
328 has no place to find the dimensions of the ole
329 object, and will not be able to draw it
331 OutGrf(*mpParentFrame
);
334 OutputField(0, ww::eEMBED
, aEmptyStr
,
335 WRITEFIELD_END
| WRITEFIELD_CLOSE
);
337 if (bEndCR
) //No newline in inline case
344 void WW8Export::OutputLinkedOLE( const OUString
& rOleId
)
346 uno::Reference
< embed::XStorage
> xDocStg
= pDoc
->GetDocStorage();
347 uno::Reference
< embed::XStorage
> xOleStg
= xDocStg
->openStorageElement( "OLELinks", embed::ElementModes::READ
);
348 SotStorageRef xObjSrc
= SotStorage::OpenOLEStorage( xOleStg
, rOleId
, STREAM_READ
);
350 SotStorageRef xObjStg
= GetWriter().GetStorage().OpenSotStorage(
351 OUString(SL::aObjectPool
), STREAM_READWRITE
|
352 STREAM_SHARE_DENYALL
);
354 if( xObjStg
.Is() && xObjSrc
.Is() )
356 SotStorageRef xOleDst
= xObjStg
->OpenSotStorage( rOleId
,
357 STREAM_READWRITE
| STREAM_SHARE_DENYALL
);
359 xObjSrc
->CopyTo( xOleDst
);
361 if ( !xOleDst
->GetError( ) )
365 // Ouput the cPicLocation attribute
366 ww::bytes
* pBuf
= new ww::bytes();
367 GetWriter().InsUInt16( *pBuf
, NS_sprm::LN_CPicLocation
);
368 GetWriter().InsUInt32( *pBuf
, rOleId
.copy( 1 ).toInt32() );
370 GetWriter().InsUInt16( *pBuf
, NS_sprm::LN_CFOle2
);
371 pBuf
->push_back( 1 );
373 GetWriter().InsUInt16( *pBuf
, NS_sprm::LN_CFSpec
);
374 pBuf
->push_back( 1 );
376 GetWriter().InsUInt16( *pBuf
, NS_sprm::LN_CFObj
);
377 pBuf
->push_back( 1 );
379 pChpPlc
->AppendFkpEntry( Strm().Tell(), pBuf
->size(), pBuf
->data() );
385 void WW8Export::OutGrf(const sw::Frame
&rFrame
)
387 //Added for i120568,the hyperlink info within a graphic whose anchor type is "As character"
388 //will be exported to ensure the fidelity
389 const SwFmtURL
& rURL
= rFrame
.GetFrmFmt().GetAttrSet().GetURL();
390 bool bURLStarted
= false;
391 if( rURL
.GetURL().Len() && rFrame
.GetWriterType() == sw::Frame::eGraphic
)
394 m_pAttrOutput
->StartURL( rURL
.GetURL(), rURL
.GetTargetFrameName() );
397 // Store the graphic settings in GrfNode so they may be written-out later
398 pGrf
->Insert(rFrame
);
400 pChpPlc
->AppendFkpEntry( Strm().Tell(), pO
->size(), pO
->data() );
404 // linked, as-character anchored graphics have to be exported as fields.
405 const SwGrfNode
* pGrfNd
= rFrame
.IsInline() && rFrame
.GetContent()
406 ? rFrame
.GetContent()->GetGrfNode() : 0;
407 if ( pGrfNd
&& pGrfNd
->IsLinkedFile() )
409 String
sStr( FieldString(ww::eINCLUDEPICTURE
) );
410 sStr
.AppendAscii(" \"");
415 pGrfNd
->GetFileFilterNms( &aFileURL
, 0 );
419 sStr
.AppendAscii("\" \\d");
421 OutputField( 0, ww::eINCLUDEPICTURE
, sStr
,
422 WRITEFIELD_START
| WRITEFIELD_CMD_START
| WRITEFIELD_CMD_END
);
425 WriteChar( (char)1 ); // paste graphic symbols in the main text
427 sal_uInt8 aArr
[ 18 ];
428 sal_uInt8
* pArr
= aArr
;
430 const SwFrmFmt
&rFlyFmt
= rFrame
.GetFrmFmt();
431 const RndStdIds eAn
= rFlyFmt
.GetAttrSet().GetAnchor(false).GetAnchorId();
432 if (eAn
== FLY_AS_CHAR
)
434 sal_Int16 eVert
= rFlyFmt
.GetVertOrient().GetVertOrient();
435 if ((eVert
== text::VertOrientation::CHAR_CENTER
) || (eVert
== text::VertOrientation::LINE_CENTER
))
438 //The default for word in vertical text mode is to center,
439 //otherwise a sub/super script hack is employed
440 if (pOutFmtNode
&& pOutFmtNode
->ISA(SwCntntNode
) )
442 const SwTxtNode
* pTxtNd
= (const SwTxtNode
*)pOutFmtNode
;
443 SwPosition
aPos(*pTxtNd
);
444 bVert
= pDoc
->IsInVerticalText(aPos
);
448 SwTwips nHeight
= rFlyFmt
.GetFrmSize().GetHeight();
449 nHeight
/=20; //nHeight was in twips, want it in half points, but
450 //then half of total height.
451 long nFontHeight
= ((const SvxFontHeightItem
&)
452 GetItem(RES_CHRATR_FONTSIZE
)).GetHeight();
453 nHeight
-=nFontHeight
/20;
456 Set_UInt16( pArr
, NS_sprm::LN_CHpsPos
);
458 Set_UInt8( pArr
, 101 );
459 Set_UInt16( pArr
, -((sal_Int16
)nHeight
));
466 Set_UInt16( pArr
, 0x855 );
468 Set_UInt8( pArr
, 117 );
469 Set_UInt8( pArr
, 1 );
473 Set_UInt16( pArr
, NS_sprm::LN_CPicLocation
);
476 Set_UInt8( pArr
, 68 );
477 Set_UInt8( pArr
, 4 );
479 Set_UInt32( pArr
, GRF_MAGIC_321
);
481 // vary Magic, so that different graphic attributes will not be merged
482 static sal_uInt8 nAttrMagicIdx
= 0;
484 Set_UInt8( pArr
, nAttrMagicIdx
++ );
485 pChpPlc
->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr
- aArr
), aArr
);
488 // Check, if graphic isn't exported as-character anchored.
489 // Otherwise, an additional paragraph is exported for a graphic, which is
490 // forced to be treated as inline, because it's anchored inside another frame.
491 if ( !rFrame
.IsInline() &&
492 ( ((eAn
== FLY_AT_PARA
) && ( bWrtWW8
|| !IsInTable() )) ||
493 (eAn
== FLY_AT_PAGE
)) )
495 WriteChar( (char)0x0d ); // close the surrounding frame with CR
497 static sal_uInt8 nSty
[2] = { 0, 0 };
498 pO
->insert( pO
->end(), nSty
, nSty
+2 ); // Style #0
499 bool bOldGrf
= bOutGrf
;
502 OutputFormat( rFrame
.GetFrmFmt(), false, false, true ); // Fly-Attrs
505 pPapPlc
->AppendFkpEntry( Strm().Tell(), pO
->size(), pO
->data() );
509 // linked, as-character anchored graphics have to be exported as fields.
510 else if ( pGrfNd
&& pGrfNd
->IsLinkedFile() )
512 OutputField( 0, ww::eINCLUDEPICTURE
, String(), WRITEFIELD_CLOSE
);
514 //Added for i120568,the hyperlink info within a graphic whose anchor type is
515 //"As character" will be exported to ensure the fidelity
517 m_pAttrOutput
->EndURL();
520 GraphicDetails
& GraphicDetails::operator=(const GraphicDetails
&rOther
)
522 maFly
= rOther
.maFly
;
523 mnPos
= rOther
.mnPos
;
524 mnWid
= rOther
.mnWid
;
525 mnHei
= rOther
.mnHei
;
529 void SwWW8WrGrf::Insert(const sw::Frame
&rFly
)
531 const Size
aSize( rFly
.GetLayoutSize() );
532 const sal_uInt16 nWidth
= static_cast< sal_uInt16
>(aSize
.Width());
533 const sal_uInt16 nHeight
= static_cast< sal_uInt16
>(aSize
.Height());
534 maDetails
.push_back(GraphicDetails(rFly
, nWidth
, nHeight
));
537 void SwWW8WrGrf::WritePICFHeader(SvStream
& rStrm
, const sw::Frame
&rFly
,
538 sal_uInt16 mm
, sal_uInt16 nWidth
, sal_uInt16 nHeight
, const SwAttrSet
* pAttrSet
)
540 sal_Int16 nXSizeAdd
= 0, nYSizeAdd
= 0;
541 sal_Int16 nCropL
= 0, nCropR
= 0, nCropT
= 0, nCropB
= 0;
543 // write Crop-Attribut content in Header ( if available )
544 const SfxPoolItem
* pItem
;
545 if (pAttrSet
&& (SFX_ITEM_ON
546 == pAttrSet
->GetItemState(RES_GRFATR_CROPGRF
, false, &pItem
)))
548 const SwCropGrf
& rCr
= *(SwCropGrf
*)pItem
;
549 nCropL
= (sal_Int16
)rCr
.GetLeft();
550 nCropR
= (sal_Int16
)rCr
.GetRight();
551 nCropT
= (sal_Int16
)rCr
.GetTop();
552 nCropB
= (sal_Int16
)rCr
.GetBottom();
553 nXSizeAdd
= nXSizeAdd
- (sal_Int16
)( rCr
.GetLeft() + rCr
.GetRight() );
554 nYSizeAdd
= nYSizeAdd
- (sal_Int16
)( rCr
.GetTop() + rCr
.GetBottom() );
557 Size
aGrTwipSz(rFly
.GetSize());
558 bool bWrtWW8
= rWrt
.bWrtWW8
;
559 sal_uInt16 nHdrLen
= bWrtWW8
? 0x44 : 0x3A;
561 sal_uInt8 aArr
[ 0x44 ] = { 0 };
563 sal_uInt8
* pArr
= aArr
+ 0x2E; // Do borders first
565 const SwAttrSet
& rAttrSet
= rFly
.GetFrmFmt().GetAttrSet();
566 if (SFX_ITEM_ON
== rAttrSet
.GetItemState(RES_BOX
, false, &pItem
))
568 const SvxBoxItem
* pBox
= (const SvxBoxItem
*)pItem
;
571 bool bShadow
= false; // Shadow ?
572 const SvxShadowItem
* pSI
=
573 sw::util::HasItem
<SvxShadowItem
>(rAttrSet
, RES_SHADOW
);
576 bShadow
= (pSI
->GetLocation() != SVX_SHADOW_NONE
) &&
577 (pSI
->GetWidth() != 0);
580 sal_uInt8 aLnArr
[4] = { BOX_LINE_TOP
, BOX_LINE_LEFT
,
581 BOX_LINE_BOTTOM
, BOX_LINE_RIGHT
};
582 for( sal_uInt8 i
= 0; i
< 4; ++i
)
584 const ::editeng::SvxBorderLine
* pLn
= pBox
->GetLine( aLnArr
[ i
] );
588 aBrc
= rWrt
.TranslateBorderLine( *pLn
,
589 pBox
->GetDistance( aLnArr
[ i
] ), bShadow
);
592 // use importer logic to determine how large the exported
593 // border will really be in word and adjust accordingly
595 short nThick
= aBrc
.DetermineBorderProperties(!bWrtWW8
,
600 case BOX_LINE_BOTTOM
:
601 nHeight
-= bShadow
? nThick
*2 : nThick
;
602 nHeight
= nHeight
- nSpacing
;
607 nWidth
-= bShadow
? nThick
*2 : nThick
;
608 nWidth
= nWidth
- nSpacing
;
611 memcpy( pArr
, &aBrc
.aBits1
, 2);
616 memcpy( pArr
, &aBrc
.aBits2
, 2);
623 pArr
= aArr
+ 4; // skip lcb
624 Set_UInt16( pArr
, nHdrLen
); // set cbHeader
626 Set_UInt16( pArr
, mm
); // set mm
629 Just in case our original size is too big to fit inside a ushort we can
630 substitute the final size and loose on retaining the scaling factor but
631 still keep the correct display size anyway.
633 const bool bIsSubstitutedSize
= (aGrTwipSz
.Width() > SHRT_MAX
) || (aGrTwipSz
.Height() > SHRT_MAX
) ||
634 (aGrTwipSz
.Width() < 0 ) || (aGrTwipSz
.Height() < 0);
635 if ( bIsSubstitutedSize
)
637 aGrTwipSz
.Width() = nWidth
;
638 aGrTwipSz
.Height() = nHeight
;
640 using namespace sw::types
;
642 Set_UInt16(pArr
, msword_cast
<sal_uInt16
>(aGrTwipSz
.Width() * 254L / 144));
643 Set_UInt16(pArr
, msword_cast
<sal_uInt16
>(aGrTwipSz
.Height() * 254L / 144));
645 // skip hMF & rcWinMF
646 // set dxaGoal & dyaGoal
647 Set_UInt16(pArr
, msword_cast
<sal_uInt16
>(aGrTwipSz
.Width()));
648 Set_UInt16(pArr
, msword_cast
<sal_uInt16
>(aGrTwipSz
.Height()));
650 if ( aGrTwipSz
.Width() + nXSizeAdd
) // set mx
652 if ( !bIsSubstitutedSize
)
654 const double fVal
= nWidth
* 1000.0 / (aGrTwipSz
.Width() + nXSizeAdd
);
655 Set_UInt16( pArr
, (sal_uInt16
)::rtl::math::round(fVal
) );
659 Set_UInt16( pArr
, 1000 );
667 if ( aGrTwipSz
.Height() + nYSizeAdd
) // set my
669 if ( !bIsSubstitutedSize
)
671 const double fVal
= nHeight
* 1000.0 / (aGrTwipSz
.Height() + nYSizeAdd
);
672 Set_UInt16( pArr
, (sal_uInt16
)::rtl::math::round(fVal
) );
676 Set_UInt16( pArr
, 1000 );
684 if ( !bIsSubstitutedSize
)
686 Set_UInt16( pArr
, nCropL
); // set dxaCropLeft
687 Set_UInt16( pArr
, nCropT
); // set dyaCropTop
688 Set_UInt16( pArr
, nCropR
); // set dxaCropRight
689 Set_UInt16( pArr
, nCropB
); // set dyaCropBottom
696 rStrm
.Write( aArr
, nHdrLen
);
699 void SwWW8WrGrf::WriteGrfFromGrfNode(SvStream
& rStrm
, const SwGrfNode
&rGrfNd
,
700 const sw::Frame
&rFly
, sal_uInt16 nWidth
, sal_uInt16 nHeight
)
702 if (rGrfNd
.IsLinkedFile()) // Linked File
705 rGrfNd
.GetFileFilterNms( &aFileN
, 0 );
707 sal_uInt16 mm
= 94; // 94 = BMP, GIF
709 WritePICFHeader(rStrm
, rFly
, mm
, nWidth
, nHeight
,
710 rGrfNd
.GetpSwAttrSet());
711 rStrm
<< (sal_uInt8
)aFileN
.Len(); // write Pascal-String
712 SwWW8Writer::WriteString8(rStrm
, aFileN
, false,
713 RTL_TEXTENCODING_MS_1252
);
715 else // Embedded File or DDE or something like that
719 WritePICFHeader(rStrm
, rFly
, 0x64, nWidth
, nHeight
,
720 rGrfNd
.GetpSwAttrSet());
721 SwBasicEscherEx
aInlineEscher(&rStrm
, rWrt
);
722 aInlineEscher
.WriteGrfFlyFrame(rFly
.GetFrmFmt(), 0x401);
723 aInlineEscher
.WritePictures();
727 Graphic
& rGrf
= const_cast<Graphic
&>(rGrfNd
.GetGrf());
728 bool bSwapped
= rGrf
.IsSwapOut() ? true : false;
729 // immer ueber den Node einswappen!
730 const_cast<SwGrfNode
&>(rGrfNd
).SwapIn();
733 switch (rGrf
.GetType())
735 case GRAPHIC_BITMAP
: // Bitmap -> play in Metafile
738 aMeta
.Record(&aVirt
);
739 aVirt
.DrawBitmap( Point( 0,0 ), rGrf
.GetBitmap() );
742 aMeta
.SetPrefMapMode( rGrf
.GetPrefMapMode());
743 aMeta
.SetPrefSize( rGrf
.GetPrefSize());
746 case GRAPHIC_GDIMETAFILE
: // GDI ( =SV ) Metafile
747 aMeta
= rGrf
.GetGDIMetaFile();
753 WritePICFHeader(rStrm
, rFly
, 8, nWidth
, nHeight
,
754 rGrfNd
.GetpSwAttrSet());
755 WriteWindowMetafileBits(rStrm
, aMeta
);
762 //For i120928,export graphic info of bullet
763 void SwWW8WrGrf::WritePICBulletFHeader(SvStream
& rStrm
, const Graphic
&rGrf
,
764 sal_uInt16 mm
, sal_uInt16 nWidth
, sal_uInt16 nHeight
)
766 sal_Int16 nXSizeAdd
= 0, nYSizeAdd
= 0;
767 sal_Int16 nCropL
= 0, nCropR
= 0, nCropT
= 0, nCropB
= 0;
769 Size
aGrTwipSz(rGrf
.GetPrefSize());
770 bool bWrtWW8
= rWrt
.bWrtWW8
;
771 sal_uInt16 nHdrLen
= bWrtWW8
? 0x44 : 0x3A;
773 sal_uInt8 aArr
[ 0x44 ] = { 0 };
775 sal_uInt8
* pArr
= aArr
+ 0x2E; //Do borders first
777 sal_uInt8 aLnArr
[4] = { BOX_LINE_TOP
, BOX_LINE_LEFT
,
778 BOX_LINE_BOTTOM
, BOX_LINE_RIGHT
};
779 for( sal_uInt8 i
= 0; i
< 4; ++i
)
784 short nThick
= aBrc
.DetermineBorderProperties(!bWrtWW8
,
789 case BOX_LINE_BOTTOM
:
791 nHeight
= nHeight
- nSpacing
;
797 nWidth
= nWidth
- nSpacing
;
800 memcpy( pArr
, &aBrc
.aBits1
, 2);
805 memcpy( pArr
, &aBrc
.aBits2
, 2);
810 pArr
= aArr
+ 4; //skip lcb
811 Set_UInt16( pArr
, nHdrLen
); // set cbHeader
813 Set_UInt16( pArr
, mm
); // set mm
815 if ( (aGrTwipSz
.Width() * 254L / 144 > USHRT_MAX
) || (aGrTwipSz
.Height() * 254L / 144 > USHRT_MAX
)
816 || (aGrTwipSz
.Width() < 0 ) || (aGrTwipSz
.Height() < 0) )
818 aGrTwipSz
.Width() = nWidth
;
819 aGrTwipSz
.Height() = nHeight
;
821 using namespace sw::types
;
823 Set_UInt16(pArr
, msword_cast
<sal_uInt16
>(aGrTwipSz
.Width() * 254L / 144));
824 Set_UInt16(pArr
, msword_cast
<sal_uInt16
>(aGrTwipSz
.Height() * 254L / 144));
826 // skip hMF & rcWinMF
827 // set dxaGoal & dyaGoal
828 Set_UInt16(pArr
, msword_cast
<sal_uInt16
>(aGrTwipSz
.Width()));
829 Set_UInt16(pArr
, msword_cast
<sal_uInt16
>(aGrTwipSz
.Height()));
831 if( aGrTwipSz
.Width() + nXSizeAdd
) // set mx
833 double fVal
= nWidth
* 1000.0 / (aGrTwipSz
.Width() + nXSizeAdd
);
834 Set_UInt16( pArr
, (sal_uInt16
)::rtl::math::round(fVal
) );
839 if( aGrTwipSz
.Height() + nYSizeAdd
) // set my
841 double fVal
= nHeight
* 1000.0 / (aGrTwipSz
.Height() + nYSizeAdd
);
842 Set_UInt16( pArr
, (sal_uInt16
)::rtl::math::round(fVal
) );
847 Set_UInt16( pArr
, nCropL
); // set dxaCropLeft
848 Set_UInt16( pArr
, nCropT
); // set dyaCropTop
849 Set_UInt16( pArr
, nCropR
); // set dxaCropRight
850 Set_UInt16( pArr
, nCropB
); // set dyaCropBottom
852 rStrm
.Write( aArr
, nHdrLen
);
855 void SwWW8WrGrf::WriteGrfForBullet(SvStream
& rStrm
, const Graphic
&rGrf
, sal_uInt16 nWidth
, sal_uInt16 nHeight
)
859 WritePICBulletFHeader(rStrm
,rGrf
, 0x64,nWidth
,nHeight
);
860 SwBasicEscherEx
aInlineEscher(&rStrm
, rWrt
);
861 aInlineEscher
.WriteGrfBullet(rGrf
);
862 aInlineEscher
.WritePictures();
867 switch (rGrf
.GetType())
869 case GRAPHIC_BITMAP
: // Bitmap -> in Metafile abspielen
872 aMeta
.Record(&aVirt
);
873 aVirt
.DrawBitmap( Point( 0,0 ), rGrf
.GetBitmap() );
876 aMeta
.SetPrefMapMode( rGrf
.GetPrefMapMode());
877 aMeta
.SetPrefSize( rGrf
.GetPrefSize());
880 case GRAPHIC_GDIMETAFILE
: // GDI ( =SV ) Metafile
881 aMeta
= rGrf
.GetGDIMetaFile();
886 WritePICBulletFHeader(rStrm
, rGrf
, 8, nWidth
, nHeight
);
887 WriteWindowMetafileBits(rStrm
, aMeta
);
891 void SwWW8WrGrf::WriteGraphicNode(SvStream
& rStrm
, const GraphicDetails
&rItem
)
893 sal_uInt16 nWidth
= rItem
.mnWid
;
894 sal_uInt16 nHeight
= rItem
.mnHei
;
895 sal_uInt32 nPos
= rStrm
.Tell(); // store start of graphic
897 const sw::Frame
&rFly
= rItem
.maFly
;
898 switch (rFly
.GetWriterType())
900 case sw::Frame::eGraphic
:
902 const SwNode
*pNode
= rItem
.maFly
.GetContent();
903 const SwGrfNode
*pNd
= pNode
? pNode
->GetGrfNode() : 0;
904 OSL_ENSURE(pNd
, "Impossible");
906 WriteGrfFromGrfNode(rStrm
, *pNd
, rItem
.maFly
, nWidth
, nHeight
);
909 //For i120928,add branch to export graphic of bullet
910 case sw::Frame::eBulletGrf
:
912 if (rItem
.maFly
.HasGraphic())
914 const Graphic
& rGrf
= rItem
.maFly
.GetGraphic();
915 WriteGrfForBullet(rStrm
, rGrf
, nWidth
, nHeight
);
920 case sw::Frame::eOle
:
922 #ifdef OLE_PREVIEW_AS_EMF
923 const SwNode
*pNode
= rItem
.maFly
.GetContent();
924 const SwOLENode
*pNd
= pNode
? pNode
->GetOLENode() : 0;
925 OSL_ENSURE(pNd
, "Impossible");
928 SwOLENode
*pOleNd
= const_cast<SwOLENode
*>(pNd
);
929 OSL_ENSURE( pOleNd
, " Wer hat den OleNode versteckt ?" );
930 SwOLEObj
& rSObj
= pOleNd
->GetOLEObj();
931 uno::Reference
< embed::XEmbeddedObject
> rObj( rSObj
.GetOleRef() );
933 comphelper::EmbeddedObjectContainer
aCnt( pOleNd
->GetDoc()->GetDocStorage() );
935 SvStream
* pGraphicStream
= ::utl::UcbStreamHelper::CreateStream( aCnt
.GetGraphicStream( rObj
) );
936 OSL_ENSURE( pGraphicStream
&& !pGraphicStream
->GetError(), "No graphic stream available!" );
937 if ( pGraphicStream
&& !pGraphicStream
->GetError() )
940 GraphicFilter
& rGF
= GraphicFilter::GetGraphicFilter();
941 if( rGF
.ImportGraphic( aGr
, aEmptyStr
, *pGraphicStream
, GRFILTER_FORMAT_DONTKNOW
) == GRFILTER_OK
)
943 //TODO/LATER: do we really want to use GDIMetafile?!
945 aMtf
= aGr
.GetGDIMetaFile();
947 aMtf
.Play(Application::GetDefaultDevice(), Point(0, 0),
949 WritePICFHeader(rStrm
, rFly
, 8, nWidth
, nHeight
,
950 pNd
->GetpSwAttrSet());
951 WriteWindowMetafileBits(rStrm
, aMtf
);
955 delete pGraphicStream
;
959 //Convert this ole2 preview in ww8+ to an EMF for better unicode
960 //support (note that at this moment this breaks StarSymbol
961 //using graphics because I need to embed starsymbol in exported
963 WritePICFHeader(rStrm
, rFly
, 0x64, nWidth
, nHeight
,
964 pNd
->GetpSwAttrSet());
965 SwBasicEscherEx
aInlineEscher(&rStrm
, rWrt
);
966 aInlineEscher
.WriteOLEFlyFrame(rFly
.GetFrmFmt(), 0x401);
967 aInlineEscher
.WritePictures();
971 SwOLENode
*pOleNd
= const_cast<SwOLENode
*>(pNd
);
972 OSL_ENSURE( pOleNd
, " Wer hat den OleNode versteckt ?" );
973 SwOLEObj
& rSObj
= pOleNd
->GetOLEObj();
975 // TODO/LATER: do we need to load object?
976 Graphic
* pGr
= SdrOle2Obj::GetGraphicFromObject( pOleNd
->GetDoc()->GetDocStorage(), rObj
);
978 //TODO/LATER: do we really want to use GDIMetafile?!
981 aMtf
= pGr
->GetGDIMetaFile();
983 Size
aS(aMtf
.GetPrefSize());
985 aMtf
.Play(Application::GetDefaultDevice(), Point(0, 0),
988 WritePICFHeader(rStrm
, rFly
, 8, nWidth
, nHeight
,
989 pNd
->GetpSwAttrSet());
990 WriteWindowMetafileBits(rStrm
, aMtf
);
995 case sw::Frame::eDrawing
:
996 case sw::Frame::eTxtBox
:
997 case sw::Frame::eFormControl
:
998 OSL_ENSURE(rWrt
.bWrtWW8
,
999 "You can't try and export these in WW8 format, a filter bug");
1001 #i3958# We only export an empty dummy picture frame here, this is
1002 what word does the escher export should contain an anchored to
1003 character element which is drawn over this dummy and the whole
1004 shebang surrounded with a SHAPE field. This isn't *my* hack :-),
1009 WritePICFHeader(rStrm
, rFly
, 0x64, nWidth
, nHeight
);
1010 SwBasicEscherEx
aInlineEscher(&rStrm
, rWrt
);
1011 aInlineEscher
.WriteEmptyFlyFrame(rFly
.GetFrmFmt(), 0x401);
1016 "Some inline export not implemented, remind cmc before we ship :-)");
1020 sal_uInt32 nPos2
= rStrm
.Tell(); // store the end
1023 UInt32ToSVBT32( nPos2
- nPos
, nLen
); // calculate graphic length
1024 rStrm
.Write( nLen
, 4 ); // patch it in the header
1025 rStrm
.Seek( nPos2
); // restore Pos
1028 // SwWW8WrGrf::Write() is called after the text.
1029 // It writes out all the graphics and remembers the file locations of the graphics,
1030 // so when writing the attributes of the items it can be patched into PicLocFc-SPRMs.
1031 // The search in the attributes for the Magic sal_uLong and patching
1032 // happens when writing the attributes. Class SwWW8WrGrf-Klasse provides with
1033 // GetFPos() sequentially the positions
1034 void SwWW8WrGrf::Write()
1036 SvStream
& rStrm
= *rWrt
.pDataStrm
;
1037 myiter aEnd
= maDetails
.end();
1038 for (myiter aIter
= maDetails
.begin(); aIter
!= aEnd
; ++aIter
)
1040 sal_uInt32 nPos
= rStrm
.Tell(); // align to 4 Bytes
1042 SwWW8Writer::FillCount( rStrm
, 4 - ( nPos
& 0x3 ) );
1044 bool bDuplicated
= false;
1045 for (myiter aIter2
= maDetails
.begin(); aIter2
!= aIter
; ++aIter2
)
1047 if (*aIter2
== *aIter
)
1049 aIter
->mnPos
= aIter2
->mnPos
;
1057 aIter
->mnPos
= rStrm
.Tell();
1058 WriteGraphicNode(rStrm
, *aIter
);
1063 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */