bump product version to 4.1.6.2
[LibreOffice.git] / sw / source / filter / ww8 / wrtw8esh.cxx
blob5e7add30c33f6146f924d952986ad5b658f24063
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <com/sun/star/embed/Aspects.hpp>
22 #include <hintids.hxx>
24 #include <vcl/cvtgrf.hxx>
25 #include <vcl/virdev.hxx>
26 #include <com/sun/star/drawing/XShape.hpp>
27 #include <vcl/svapp.hxx>
28 #include <sot/storage.hxx>
29 #include <vcl/graphicfilter.hxx>
30 #include <svl/itemiter.hxx>
31 #include <svx/svdobj.hxx>
32 #include <svx/svdotext.hxx>
33 #include <svx/svdmodel.hxx>
34 #include <svx/svdpage.hxx>
35 #include <editeng/outlobj.hxx>
36 #include <editeng/editobj.hxx>
37 #include <svx/unoshape.hxx>
38 #include <editeng/brushitem.hxx>
39 #include <editeng/boxitem.hxx>
40 #include <editeng/lrspitem.hxx>
41 #include <editeng/ulspitem.hxx>
42 #include <editeng/fontitem.hxx>
43 #include <editeng/frmdiritem.hxx>
44 #include <svx/svdoole2.hxx>
45 #include <editeng/editeng.hxx>
46 #include <editeng/flditem.hxx>
47 #include <unotools/ucbstreamhelper.hxx>
48 #include <svx/fmglob.hxx>
49 #include <svx/svdouno.hxx>
50 #include <svx/unoapi.hxx>
52 // #i71538#
53 #include <svx/svdview.hxx>
54 #include <fmtcnct.hxx>
55 #include <fmtanchr.hxx>
56 #include <fmtsrnd.hxx>
57 #include <fmtornt.hxx>
58 #include <fmtfsize.hxx>
59 #include <fmtfollowtextflow.hxx> // #i30669#
60 #include <dcontact.hxx>
61 #include <frmfmt.hxx>
62 #include <flyfrm.hxx>
63 #include <pagefrm.hxx>
64 #include <frmatr.hxx>
65 #include <fmtcntnt.hxx>
66 #include <ndindex.hxx>
67 #include <doc.hxx>
68 #include <docary.hxx>
69 #include <pam.hxx>
70 #include <swrect.hxx>
71 #include <ndgrf.hxx>
72 #include <grfatr.hxx>
73 #include <ndole.hxx>
74 #include <unodraw.hxx>
75 #include <pagedesc.hxx>
76 #include <ww8par.hxx>
77 #include <breakit.hxx>
78 #include <com/sun/star/i18n/ScriptType.hpp>
79 #include "ww8attributeoutput.hxx"
80 #include "writerhelper.hxx"
81 #include "writerwordglue.hxx"
82 #include "wrtww8.hxx"
83 #include "escher.hxx"
84 #include <ndtxt.hxx>
85 #include "WW8FFData.hxx"
86 #include <com/sun/star/beans/XPropertyContainer.hpp>
87 #include <com/sun/star/beans/XPropertySet.hpp>
88 #include <com/sun/star/beans/PropertyAttribute.hpp>
89 #include <com/sun/star/form/XFormComponent.hpp>
90 #include "docsh.hxx"
91 #include <oox/ole/olehelper.hxx>
92 #include <fstream>
93 #include <unotools/streamwrap.hxx>
96 using ::editeng::SvxBorderLine;
97 using namespace com::sun::star;
98 using namespace sw::util;
99 using namespace sw::types;
100 using namespace nsFieldFlags;
102 namespace
104 /// Get the Z ordering number for a DrawObj in a WW8Export.
105 /// @param rWrt The containing WW8Export.
106 /// @param pObj pointer to the drawing object.
107 /// @returns The ordering number.
108 static sal_uLong lcl_getSdrOrderNumber(const WW8Export& rWrt, DrawObj *pObj)
110 return rWrt.GetSdrOrdNum(pObj->maCntnt.GetFrmFmt());
113 /// A function object to act as a predicate comparing the ordering numbers
114 /// of two drawing obejcts in a WW8Export.
115 class CompareDrawObjs
117 private:
118 const WW8Export& wrt;
120 public:
121 CompareDrawObjs(const WW8Export& rWrt) : wrt(rWrt) {};
122 bool operator()(DrawObj *a, DrawObj *b) const
124 sal_uLong aSort = lcl_getSdrOrderNumber(wrt, a);
125 sal_uLong bSort = lcl_getSdrOrderNumber(wrt, b);
126 return aSort < bSort;
130 /// Make a z-order sorted copy of a collection of DrawObj objects.
131 /// @param rWrt The containing WW8Export.
132 /// @param rSrcArr The source array.
133 /// @param rDstArr The destination array.
134 static void lcl_makeZOrderArray(const WW8Export& rWrt,
135 std::vector<DrawObj> &rSrcArr,
136 std::vector<DrawObj*> &rDstArr)
138 rDstArr.clear();
139 rDstArr.reserve(rSrcArr.size());
140 for(size_t i = 0; i < rSrcArr.size(); ++i)
142 rDstArr.push_back( &rSrcArr[i] );
144 std::sort(rDstArr.begin(), rDstArr.end(), CompareDrawObjs(rWrt));
149 // get a part fix for this type of element
150 bool WW8Export::MiserableFormFieldExportHack(const SwFrmFmt& rFrmFmt)
152 OSL_ENSURE(bWrtWW8, "Not allowed");
153 if (!bWrtWW8)
154 return false;
155 bool bHack = false;
156 const SdrObject *pObject = rFrmFmt.FindRealSdrObject();
157 if (pObject && pObject->GetObjInventor() == FmFormInventor)
159 if (SdrUnoObj *pFormObj = PTR_CAST(SdrUnoObj,pObject))
161 uno::Reference< awt::XControlModel > xControlModel =
162 pFormObj->GetUnoControlModel();
163 uno::Reference< lang::XServiceInfo > xInfo(xControlModel,
164 uno::UNO_QUERY);
165 uno::Reference<beans::XPropertySet> xPropSet(xControlModel, uno::UNO_QUERY);
166 if (xInfo->supportsService("com.sun.star.form.component.ComboBox"))
168 DoComboBox(xPropSet);
169 bHack = true;
171 else if (xInfo->supportsService("com.sun.star.form.component.CheckBox"))
173 DoCheckBox(xPropSet);
174 bHack = true;
178 return bHack;
182 void WW8Export::DoComboBox(uno::Reference<beans::XPropertySet> xPropSet)
184 OUString sSelected;
185 uno::Sequence<OUString> aListItems;
186 xPropSet->getPropertyValue("StringItemList") >>= aListItems;
187 sal_Int32 nNoStrings = aListItems.getLength();
188 if (nNoStrings)
190 uno::Any aTmp = xPropSet->getPropertyValue("DefaultText");
191 const OUString *pStr = (const OUString *)aTmp.getValue();
192 if (pStr)
193 sSelected = *pStr;
196 OUString sName;
198 uno::Any aTmp = xPropSet->getPropertyValue("Name");
199 const OUString *pStr = (const OUString *)aTmp.getValue();
200 if (pStr)
201 sName = *pStr;
205 OUString sHelp;
207 // property "Help" does not exist and due to the no-existence an exception is thrown.
210 uno::Any aTmp = xPropSet->getPropertyValue("HelpText");
211 const OUString *pStr = (const OUString *)aTmp.getValue();
212 if (pStr)
213 sHelp = *pStr;
215 catch( const uno::Exception& )
219 OUString sToolTip;
221 uno::Any aTmp = xPropSet->getPropertyValue("Name");
222 const OUString *pStr = (const OUString *)aTmp.getValue();
223 if (pStr)
224 sToolTip = *pStr;
227 DoComboBox(sName, sHelp, sToolTip, sSelected, aListItems);
230 void WW8Export::DoComboBox(const OUString &rName,
231 const OUString &rHelp,
232 const OUString &rToolTip,
233 const OUString &rSelected,
234 uno::Sequence<OUString> &rListItems)
236 OSL_ENSURE(bWrtWW8, "Not allowed");
237 if (!bWrtWW8)
238 return;
239 OutputField(0, ww::eFORMDROPDOWN, FieldString(ww::eFORMDROPDOWN),
240 WRITEFIELD_START | WRITEFIELD_CMD_START);
241 // write the refence to the "picture" structure
242 sal_uLong nDataStt = pDataStrm->Tell();
243 pChpPlc->AppendFkpEntry( Strm().Tell() );
245 WriteChar( 0x01 );
247 static sal_uInt8 aArr1[] =
249 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
250 0x06, 0x08, 0x01, // sprmCFData
251 0x55, 0x08, 0x01, // sprmCFSpec
252 0x02, 0x08, 0x01 // sprmCFFldVanish
254 sal_uInt8* pDataAdr = aArr1 + 2;
255 Set_UInt32( pDataAdr, nDataStt );
257 pChpPlc->AppendFkpEntry(Strm().Tell(), sizeof(aArr1), aArr1);
259 OutputField(0, ww::eFORMDROPDOWN, FieldString(ww::eFORMDROPDOWN),
260 WRITEFIELD_CLOSE);
262 ::sw::WW8FFData aFFData;
264 aFFData.setType(2);
265 aFFData.setName(rName);
266 aFFData.setHelp(rHelp);
267 aFFData.setStatus(rToolTip);
269 sal_uInt32 nListItems = rListItems.getLength();
271 for (sal_uInt32 i = 0; i < nListItems; i++)
273 if (i < 0x20 && rSelected == rListItems[i])
274 aFFData.setResult(::sal::static_int_cast<sal_uInt8>(i));
275 aFFData.addListboxEntry(rListItems[i]);
278 aFFData.Write(pDataStrm);
281 void WW8Export::DoCheckBox(uno::Reference<beans::XPropertySet> xPropSet)
283 uno::Reference<beans::XPropertySetInfo> xPropSetInfo =
284 xPropSet->getPropertySetInfo();
286 OutputField(0, ww::eFORMCHECKBOX, FieldString(ww::eFORMCHECKBOX),
287 WRITEFIELD_START | WRITEFIELD_CMD_START);
288 // write the refence to the "picture" structure
289 sal_uLong nDataStt = pDataStrm->Tell();
290 pChpPlc->AppendFkpEntry( Strm().Tell() );
292 WriteChar( 0x01 );
293 static sal_uInt8 aArr1[] = {
294 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
296 0x06, 0x08, 0x01, // sprmCFData
297 0x55, 0x08, 0x01, // sprmCFSpec
298 0x02, 0x08, 0x01 // sprmCFFldVanish
300 sal_uInt8* pDataAdr = aArr1 + 2;
301 Set_UInt32( pDataAdr, nDataStt );
303 pChpPlc->AppendFkpEntry(Strm().Tell(),
304 sizeof( aArr1 ), aArr1 );
306 ::sw::WW8FFData aFFData;
308 aFFData.setType(1);
309 aFFData.setCheckboxHeight(0x14);
311 sal_Int16 nTemp = 0;
312 xPropSet->getPropertyValue("DefaultState") >>= nTemp;
313 aFFData.setDefaultResult(nTemp);
315 xPropSet->getPropertyValue("State") >>= nTemp;
316 aFFData.setResult(nTemp);
318 OUString aStr;
319 static OUString sName("Name");
320 if (xPropSetInfo->hasPropertyByName(sName))
322 xPropSet->getPropertyValue(sName) >>= aStr;
323 aFFData.setName(aStr);
326 static OUString sHelpText("HelpText");
327 if (xPropSetInfo->hasPropertyByName(sHelpText))
329 xPropSet->getPropertyValue(sHelpText) >>= aStr;
330 aFFData.setHelp(aStr);
332 static OUString sHelpF1Text("HelpF1Text");
333 if (xPropSetInfo->hasPropertyByName(sHelpF1Text))
335 xPropSet->getPropertyValue(sHelpF1Text) >>= aStr;
336 aFFData.setStatus(aStr);
339 aFFData.Write(pDataStrm);
341 OutputField(0, ww::eFORMCHECKBOX, aEmptyStr, WRITEFIELD_CLOSE);
344 void WW8Export::DoFormText(const SwInputField * pFld)
346 OutputField(0, ww::eFORMTEXT, FieldString(ww::eFORMTEXT),
347 WRITEFIELD_START | WRITEFIELD_CMD_START);
348 // write the refence to the "picture" structure
349 sal_uLong nDataStt = pDataStrm->Tell();
350 pChpPlc->AppendFkpEntry( Strm().Tell() );
352 WriteChar( 0x01 );
353 static sal_uInt8 aArr1[] = {
354 0x02, 0x08, 0x81, // sprmCFFldVanish
355 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
357 0x06, 0x08, 0x01, // sprmCFData
358 0x55, 0x08, 0x01 // sprmCFSpec
360 sal_uInt8* pDataAdr = aArr1 + 5;
361 Set_UInt32( pDataAdr, nDataStt );
363 pChpPlc->AppendFkpEntry(Strm().Tell(),
364 sizeof( aArr1 ), aArr1 );
366 ::sw::WW8FFData aFFData;
368 aFFData.setType(0);
369 aFFData.setName(pFld->GetPar2());
370 aFFData.setHelp(pFld->GetHelp());
371 aFFData.setStatus(pFld->GetToolTip());
372 aFFData.Write(pDataStrm);
374 OutputField(0, ww::eFORMTEXT, aEmptyStr, WRITEFIELD_CMD_END);
376 String const fieldStr( pFld->ExpandField(true) );
377 SwWW8Writer::WriteString16(Strm(), fieldStr, false);
379 static sal_uInt8 aArr2[] = {
380 0x03, 0x6a, 0x00, 0x00, 0x00, 0x00, // sprmCPicLocation
381 0x55, 0x08, 0x01, // sprmCFSpec
382 0x75, 0x08, 0x01 // ???
385 pDataAdr = aArr2 + 2;
386 Set_UInt32( pDataAdr, nDataStt );
387 pChpPlc->AppendFkpEntry(Strm().Tell(),
388 sizeof( aArr2 ), aArr2 );
390 OutputField(0, ww::eFORMTEXT, aEmptyStr, WRITEFIELD_CLOSE);
393 PlcDrawObj::~PlcDrawObj()
397 //Its irritating to have to change the RTL frames position into LTR ones
398 //so that word will have to place them in the right place. Doubly so that
399 //the SO drawings and writer frames have different ideas themselves as to
400 //how to be positioned when in RTL mode!
401 bool RTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth,
402 sal_Int16 eHoriOri, sal_Int16 eHoriRel, SwTwips nPageLeft,
403 SwTwips nPageRight, SwTwips nPageSize)
405 bool bRet = false;
406 if (eHoriOri == text::HoriOrientation::NONE)
408 if (eHoriRel == text::RelOrientation::PAGE_FRAME)
410 rLeft = nPageSize - rLeft;
411 bRet = true;
413 else if (
414 (eHoriRel == text::RelOrientation::PAGE_PRINT_AREA) ||
415 (eHoriRel == text::RelOrientation::FRAME) ||
416 (eHoriRel == text::RelOrientation::PRINT_AREA)
419 rLeft = nPageSize - nPageLeft - nPageRight - rLeft;
420 bRet = true;
423 if (bRet)
424 rLeft -= nWidth;
425 return bRet;
428 bool RTLDrawingsHack(long &rLeft, long /*nWidth*/,
429 sal_Int16 eHoriOri, sal_Int16 eHoriRel, SwTwips nPageLeft,
430 SwTwips nPageRight, SwTwips nPageSize)
432 bool bRet = false;
433 if (eHoriOri == text::HoriOrientation::NONE)
435 if (eHoriRel == text::RelOrientation::PAGE_FRAME)
437 rLeft = nPageSize + rLeft;
438 bRet = true;
440 else if (
441 (eHoriRel == text::RelOrientation::PAGE_PRINT_AREA) ||
442 (eHoriRel == text::RelOrientation::FRAME) ||
443 (eHoriRel == text::RelOrientation::PRINT_AREA)
446 rLeft = nPageSize - nPageLeft - nPageRight + rLeft;
447 bRet = true;
450 return bRet;
453 bool WW8Export::MiserableRTLFrmFmtHack(SwTwips &rLeft, SwTwips &rRight,
454 const sw::Frame &rFrmFmt)
456 //Require nasty bidi swap
457 if (FRMDIR_HORI_RIGHT_TOP != pDoc->GetTextDirection(rFrmFmt.GetPosition()))
458 return false;
460 SwTwips nWidth = rRight - rLeft;
461 SwTwips nPageLeft, nPageRight;
462 SwTwips nPageSize = CurrentPageWidth(nPageLeft, nPageRight);
464 const SwFmtHoriOrient& rHOr = rFrmFmt.GetFrmFmt().GetHoriOrient();
466 bool bRet = false;
467 sw::Frame::WriterSource eSource = rFrmFmt.GetWriterType();
468 if (eSource == sw::Frame::eDrawing || eSource == sw::Frame::eFormControl)
470 if (RTLDrawingsHack(rLeft, nWidth, rHOr.GetHoriOrient(),
471 rHOr.GetRelationOrient(), nPageLeft, nPageRight, nPageSize))
473 bRet = true;
476 else
478 if (RTLGraphicsHack(rLeft, nWidth, rHOr.GetHoriOrient(),
479 rHOr.GetRelationOrient(), nPageLeft, nPageRight, nPageSize))
481 bRet = true;
484 if (bRet)
485 rRight = rLeft + nWidth;
486 return bRet;
489 void PlcDrawObj::WritePlc( WW8Export& rWrt ) const
491 if (8 > rWrt.pFib->nVersion) // Cannot export drawobject in vers 7-
492 return;
494 sal_uInt32 nFcStart = rWrt.pTableStrm->Tell();
496 if (!maDrawObjs.empty())
498 // write CPs
499 WW8Fib& rFib = *rWrt.pFib;
500 WW8_CP nCpOffs = GetCpOffset(rFib);
502 cDrawObjIter aEnd = maDrawObjs.end();
503 cDrawObjIter aIter;
505 for (aIter = maDrawObjs.begin(); aIter < aEnd; ++aIter)
506 SwWW8Writer::WriteLong(*rWrt.pTableStrm, aIter->mnCp - nCpOffs);
508 SwWW8Writer::WriteLong(*rWrt.pTableStrm, rFib.ccpText + rFib.ccpFtn +
509 rFib.ccpHdr + rFib.ccpEdn + rFib.ccpTxbx + rFib.ccpHdrTxbx + 1);
511 for (aIter = maDrawObjs.begin(); aIter < aEnd; ++aIter)
513 // write the fspa-struct
514 const sw::Frame &rFrmFmt = aIter->maCntnt;
515 const SwFrmFmt &rFmt = rFrmFmt.GetFrmFmt();
516 const SdrObject* pObj = rFmt.FindRealSdrObject();
518 Rectangle aRect;
519 SwFmtVertOrient rVOr = rFmt.GetVertOrient();
520 SwFmtHoriOrient rHOr = rFmt.GetHoriOrient();
521 // #i30669# - convert the positioning attributes.
522 // Most positions are converted, if layout information exists.
523 const bool bPosConverted =
524 WinwordAnchoring::ConvertPosition( rHOr, rVOr, rFmt );
526 Point aObjPos;
527 if (RES_FLYFRMFMT == rFmt.Which())
529 SwRect aLayRect(rFmt.FindLayoutRect(false, &aObjPos));
530 // the Object is not visible - so get the values from
531 // the format. The Position may not be correct.
532 if( aLayRect.IsEmpty() )
533 aRect.SetSize( rFmt.GetFrmSize().GetSize() );
534 else
536 // #i56090# Do not only consider the first client
537 // Note that we actually would have to find the maximum size of the
538 // frame format clients. However, this already should work in most cases.
539 const SwRect aSizeRect(rFmt.FindLayoutRect());
540 if ( aSizeRect.Width() > aLayRect.Width() )
541 aLayRect.Width( aSizeRect.Width() );
543 aRect = aLayRect.SVRect();
546 else
548 OSL_ENSURE(pObj, "wo ist das SDR-Object?");
549 if (pObj)
551 aRect = pObj->GetSnapRect();
555 // #i30669# - use converted position, if conversion is performed.
556 // Unify position determination of Writer fly frames
557 // and drawing objects.
558 if ( bPosConverted )
560 aRect.SetPos( Point( rHOr.GetPos(), rVOr.GetPos() ) );
562 else
564 aRect -= aIter->maParentPos;
565 aObjPos = aRect.TopLeft();
566 if (text::VertOrientation::NONE == rVOr.GetVertOrient())
568 // #i22673#
569 sal_Int16 eOri = rVOr.GetRelationOrient();
570 if (eOri == text::RelOrientation::CHAR || eOri == text::RelOrientation::TEXT_LINE)
571 aObjPos.Y() = -rVOr.GetPos();
572 else
573 aObjPos.Y() = rVOr.GetPos();
575 if (text::HoriOrientation::NONE == rHOr.GetHoriOrient())
576 aObjPos.X() = rHOr.GetPos();
577 aRect.SetPos( aObjPos );
580 sal_Int32 nThick = aIter->mnThick;
582 //If we are being exported as an inline hack, set
583 //corner to 0 and forget about border thickness for positioning
584 if (rFrmFmt.IsInline())
586 aRect.SetPos(Point(0,0));
587 nThick = 0;
590 // spid
591 SwWW8Writer::WriteLong(*rWrt.pTableStrm, aIter->mnShapeId);
593 SwTwips nLeft = aRect.Left() + nThick;
594 SwTwips nRight = aRect.Right() - nThick;
596 //Nasty swap for bidi if necessary
597 rWrt.MiserableRTLFrmFmtHack(nLeft, nRight, rFrmFmt);
599 //xaLeft/yaTop/xaRight/yaBottom - rel. to anchor
600 //(most of) the border is outside the graphic is word, so
601 //change dimensions to fit
602 SwWW8Writer::WriteLong(*rWrt.pTableStrm, nLeft);
603 SwWW8Writer::WriteLong(*rWrt.pTableStrm,aRect.Top() + nThick);
604 SwWW8Writer::WriteLong(*rWrt.pTableStrm, nRight);
605 SwWW8Writer::WriteLong(*rWrt.pTableStrm,aRect.Bottom() - nThick);
607 //fHdr/bx/by/wr/wrk/fRcaSimple/fBelowText/fAnchorLock
608 sal_uInt16 nFlags=0;
609 //If nFlags isn't 0x14 its overridden by the escher properties
610 if (FLY_AT_PAGE == rFmt.GetAnchor().GetAnchorId())
611 nFlags = 0x0000;
612 else
613 nFlags = 0x0014; // x-rel to text, y-rel to text
615 const SwFmtSurround& rSurr = rFmt.GetSurround();
616 sal_uInt16 nContour = rSurr.IsContour() ? 0x0080 : 0x0040;
617 SwSurround eSurround = rSurr.GetSurround();
620 #i3958#
621 The inline elements being export as anchored to character inside
622 the shape field hack are required to be wrap through so as to flow
623 over the following dummy 0x01 graphic
625 if (rFrmFmt.IsInline())
626 eSurround = SURROUND_THROUGHT;
628 switch (eSurround)
630 case SURROUND_NONE:
631 nFlags |= 0x0020;
632 break;
633 case SURROUND_THROUGHT:
634 nFlags |= 0x0060;
635 break;
636 case SURROUND_PARALLEL:
637 nFlags |= 0x0000 | nContour;
638 break;
639 case SURROUND_IDEAL:
640 nFlags |= 0x0600 | nContour;
641 break;
642 case SURROUND_LEFT:
643 nFlags |= 0x0200 | nContour;
644 break;
645 case SURROUND_RIGHT:
646 nFlags |= 0x0400 | nContour;
647 break;
648 default:
649 OSL_ENSURE(!this, "Unsupported surround type for export");
650 break;
652 if (pObj && (pObj->GetLayer() == rWrt.pDoc->GetHellId() ||
653 pObj->GetLayer() == rWrt.pDoc->GetInvisibleHellId()))
655 nFlags |= 0x4000;
659 #i3958# Required to make this inline stuff work in WordXP, not
660 needed for 2003 interestingly
662 if (rFrmFmt.IsInline())
663 nFlags |= 0x8000;
665 SwWW8Writer::WriteShort(*rWrt.pTableStrm, nFlags);
667 // cTxbx
668 SwWW8Writer::WriteLong(*rWrt.pTableStrm, 0);
671 RegisterWithFib(rFib, nFcStart, rWrt.pTableStrm->Tell() - nFcStart);
675 void MainTxtPlcDrawObj::RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
676 sal_uInt32 nLen) const
678 rFib.fcPlcfspaMom = nStart;
679 rFib.lcbPlcfspaMom = nLen;
682 WW8_CP MainTxtPlcDrawObj::GetCpOffset(const WW8Fib &) const
684 return 0;
687 void HdFtPlcDrawObj::RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
688 sal_uInt32 nLen) const
690 rFib.fcPlcfspaHdr = nStart;
691 rFib.lcbPlcfspaHdr = nLen;
694 WW8_CP HdFtPlcDrawObj::GetCpOffset(const WW8Fib &rFib) const
696 return rFib.ccpText + rFib.ccpFtn;
699 DrawObj& DrawObj::operator=(const DrawObj& rOther)
701 mnCp = rOther.mnCp;
702 mnShapeId = rOther.mnShapeId;
703 maCntnt = rOther.maCntnt;
704 maParentPos = rOther.maParentPos;
705 mnThick = rOther.mnThick;
706 mnDirection = rOther.mnDirection;
707 mnHdFtIndex = rOther.mnHdFtIndex;
708 return *this;
711 bool PlcDrawObj::Append( WW8Export& rWrt, WW8_CP nCp, const sw::Frame& rFmt,
712 const Point& rNdTopLeft )
714 bool bRet = false;
715 const SwFrmFmt &rFormat = rFmt.GetFrmFmt();
716 if (TXT_HDFT == rWrt.nTxtTyp || TXT_MAINTEXT == rWrt.nTxtTyp)
718 if (RES_FLYFRMFMT == rFormat.Which())
720 // check for textflyframe and if it is the first in a Chain
721 if (rFormat.GetCntnt().GetCntntIdx())
722 bRet = true;
724 else
725 bRet = true;
728 if (bRet)
730 DrawObj aObj(rFmt, nCp, rNdTopLeft, rWrt.TrueFrameDirection(rFormat),
731 rWrt.GetHdFtIndex());
732 maDrawObjs.push_back(aObj);
734 return bRet;
737 void DrawObj::SetShapeDetails(sal_uInt32 nId, sal_Int32 nThick)
739 mnShapeId = nId;
740 mnThick = nThick;
743 bool WW8_WrPlcTxtBoxes::WriteTxt( WW8Export& rWrt )
745 rWrt.bInWriteEscher = true;
746 WW8_CP& rccp=TXT_TXTBOX == nTyp ? rWrt.pFib->ccpTxbx : rWrt.pFib->ccpHdrTxbx;
748 bool bRet = WriteGenericTxt( rWrt, nTyp, rccp );
750 WW8_CP nCP = rWrt.Fc2Cp( rWrt.Strm().Tell() );
751 WW8Fib& rFib = *rWrt.pFib;
752 WW8_CP nMyOffset = rFib.ccpText + rFib.ccpFtn + rFib.ccpHdr + rFib.ccpAtn
753 + rFib.ccpEdn;
754 if( TXT_TXTBOX == nTyp )
755 rWrt.pFldTxtBxs->Finish( nCP, nMyOffset );
756 else
757 rWrt.pFldHFTxtBxs->Finish( nCP, nMyOffset + rFib.ccpTxbx );
758 rWrt.bInWriteEscher = false;
759 return bRet;
762 void WW8_WrPlcTxtBoxes::Append( const SdrObject& rObj, sal_uInt32 nShapeId )
764 aCntnt.push_back( &rObj );
765 aShapeIds.push_back( nShapeId );
768 const std::vector<sal_uInt32>* WW8_WrPlcTxtBoxes::GetShapeIdArr() const
770 return &aShapeIds;
774 sal_uInt32 WW8Export::GetSdrOrdNum( const SwFrmFmt& rFmt ) const
776 sal_uInt32 nOrdNum;
777 const SdrObject* pObj = rFmt.FindRealSdrObject();
778 if( pObj )
779 nOrdNum = pObj->GetOrdNum();
780 else
782 // no Layout for this format, then recalc the ordnum
783 SwFrmFmt* pFmt = (SwFrmFmt*)&rFmt;
784 nOrdNum = pDoc->GetSpzFrmFmts()->GetPos( pFmt );
786 const SdrModel* pModel = pDoc->GetDrawModel();
787 if( pModel )
788 nOrdNum += pModel->GetPage( 0 )->GetObjCount();
790 return nOrdNum;
793 void WW8Export::AppendFlyInFlys(const sw::Frame& rFrmFmt,
794 const Point& rNdTopLeft)
796 OSL_ENSURE(bWrtWW8, "this has gone horribly wrong");
797 OSL_ENSURE(!pEscher, "der EscherStream wurde schon geschrieben!");
798 if (pEscher)
799 return ;
800 PlcDrawObj *pDrwO;
801 if (TXT_HDFT == nTxtTyp)
802 pDrwO = pHFSdrObjs;
803 else
804 pDrwO = pSdrObjs;
806 if (rFrmFmt.IsInline())
808 OutputField(0, ww::eSHAPE, FieldString(ww::eSHAPE),
809 WRITEFIELD_START | WRITEFIELD_CMD_START | WRITEFIELD_CMD_END);
812 WW8_CP nCP = Fc2Cp(Strm().Tell());
813 bool bSuccess = pDrwO->Append(*this, nCP, rFrmFmt, rNdTopLeft);
814 OSL_ENSURE(bSuccess, "Couldn't export a graphical element!");
816 if (bSuccess)
818 static const sal_uInt8 aSpec8[] =
820 0x03, 0x6a, 0, 0, 0, 0, // sprmCObjLocation
821 0x55, 0x08, 1 // sprmCFSpec
823 // fSpec-Attribut true
824 // Fuer DrawObjets muss ein Spezial-Zeichen
825 // in den Text und darum ein fSpec-Attribut
826 pChpPlc->AppendFkpEntry( Strm().Tell() );
827 WriteChar( 0x8 );
828 pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aSpec8 ), aSpec8 );
830 //Need dummy picture frame
831 if (rFrmFmt.IsInline())
832 OutGrf(rFrmFmt);
835 if (rFrmFmt.IsInline())
836 OutputField(0, ww::eSHAPE, aEmptyStr, WRITEFIELD_CLOSE);
839 MSWord_SdrAttrIter::MSWord_SdrAttrIter( MSWordExportBase& rWr,
840 const EditTextObject& rEditObj, sal_uInt8 nTyp )
841 : MSWordAttrIter( rWr ), pEditObj(&rEditObj), pEditPool(0), mnTyp(nTyp)
843 NextPara( 0 );
846 void MSWord_SdrAttrIter::NextPara( sal_Int32 nPar )
848 nPara = nPar;
849 // Attributwechsel an Pos 0 wird ignoriert, da davon ausgegangen
850 // wird, dass am Absatzanfang sowieso die Attribute neu ausgegeben
851 // werden.
852 aChrTxtAtrArr.clear();
853 aChrSetArr.clear();
854 nAktSwPos = nTmpSwPos = 0;
856 SfxItemSet aSet( pEditObj->GetParaAttribs( nPara ));
857 pEditPool = aSet.GetPool();
858 eNdChrSet = ItemGet<SvxFontItem>(aSet,EE_CHAR_FONTINFO).GetCharSet();
860 if( g_pBreakIt->GetBreakIter().is() )
861 nScript = g_pBreakIt->GetBreakIter()->getScriptType( pEditObj->GetText(nPara), 0);
862 else
863 nScript = i18n::ScriptType::LATIN;
865 pEditObj->GetCharAttribs( nPara, aTxtAtrArr );
866 nAktSwPos = SearchNext( 1 );
869 rtl_TextEncoding MSWord_SdrAttrIter::GetNextCharSet() const
871 if( !aChrSetArr.empty() )
872 return aChrSetArr.back();
873 return eNdChrSet;
876 // der erste Parameter in SearchNext() liefert zurueck, ob es ein TxtAtr ist.
877 xub_StrLen MSWord_SdrAttrIter::SearchNext( xub_StrLen nStartPos )
879 sal_uInt16 nMinPos = STRING_MAXLEN;
880 for(std::vector<EECharAttrib>::const_iterator i = aTxtAtrArr.begin(); i < aTxtAtrArr.end(); ++i)
882 sal_uInt16 nPos = i->nStart; // gibt erstes Attr-Zeichen
883 if( nPos >= nStartPos && nPos <= nMinPos )
885 nMinPos = nPos;
886 SetCharSet(*i, true);
889 nPos = i->nEnd; // gibt letztes Attr-Zeichen + 1
890 if( nPos >= nStartPos && nPos < nMinPos )
892 nMinPos = nPos;
893 SetCharSet(*i, false);
896 return nMinPos;
899 void MSWord_SdrAttrIter::SetCharSet(const EECharAttrib& rAttr, bool bStart)
901 const SfxPoolItem& rItem = *rAttr.pAttr;
902 if( rItem.Which() != EE_CHAR_FONTINFO )
904 return;
907 if( bStart )
909 rtl_TextEncoding eChrSet = ((SvxFontItem&)rItem).GetCharSet();
910 aChrSetArr.push_back( eChrSet );
911 aChrTxtAtrArr.push_back( &rAttr );
913 else
915 std::vector<const EECharAttrib*>::iterator it =
916 std::find( aChrTxtAtrArr.begin(), aChrTxtAtrArr.end(), &rAttr );
917 if ( it != aChrTxtAtrArr.end() )
919 aChrTxtAtrArr.erase( it );
920 aChrSetArr.erase( aChrSetArr.begin() + (it - aChrTxtAtrArr.begin()) );
925 void MSWord_SdrAttrIter::OutEEField(const SfxPoolItem& rHt)
927 const SvxFieldItem &rField = (const SvxFieldItem &)rHt;
928 const SvxFieldData *pFld = rField.GetField();
929 if (pFld && pFld->ISA(SvxURLField))
931 sal_uInt8 nOldTxtTyp = m_rExport.nTxtTyp;
932 m_rExport.nTxtTyp = mnTyp;
933 const SvxURLField *pURL = (const SvxURLField *)pFld;
934 m_rExport.AttrOutput().StartURL( pURL->GetURL(), pURL->GetTargetFrame() );
936 const String &rStr = pURL->GetRepresentation();
937 m_rExport.AttrOutput().RawText( rStr, true, GetNodeCharSet() ); // FIXME kendy: is the 'true' actually correct here? It was here before, but... ;-)
939 m_rExport.AttrOutput().EndURL();
940 m_rExport.nTxtTyp = nOldTxtTyp;
944 void MSWord_SdrAttrIter::OutAttr( xub_StrLen nSwPos )
946 OutParaAttr(true);
948 if(!aTxtAtrArr.empty())
950 const SwModify* pOldMod = m_rExport.pOutFmtNode;
951 m_rExport.pOutFmtNode = 0;
953 const SfxItemPool* pSrcPool = pEditPool;
954 const SfxItemPool& rDstPool = m_rExport.pDoc->GetAttrPool();
956 nTmpSwPos = nSwPos;
957 sal_uInt16 nWhich, nSlotId;
958 for(std::vector<EECharAttrib>::const_iterator i = aTxtAtrArr.begin(); i < aTxtAtrArr.end(); ++i)
960 if (nSwPos >= i->nStart && nSwPos < i->nEnd)
962 nWhich = i->pAttr->Which();
963 if (nWhich == EE_FEATURE_FIELD)
965 OutEEField(*(i->pAttr));
966 continue;
968 else if (nWhich == EE_FEATURE_TAB)
970 m_rExport.WriteChar(0x9);
971 continue;
973 nSlotId = pSrcPool->GetSlotId(nWhich);
975 if (nSlotId && nWhich != nSlotId)
977 nWhich = rDstPool.GetWhich(nSlotId);
978 if (nWhich && nWhich != nSlotId &&
979 nWhich < RES_UNKNOWNATR_BEGIN &&
980 m_rExport.CollapseScriptsforWordOk(nScript,nWhich))
982 // use always the SW-Which Id !
983 SfxPoolItem* pI = i->pAttr->Clone();
984 pI->SetWhich( nWhich );
985 m_rExport.AttrOutput().OutputItem( *pI );
986 delete pI;
991 if( nSwPos < i->nStart )
992 break;
995 nTmpSwPos = 0; // HasTextItem nur in dem obigen Bereich erlaubt
996 m_rExport.pOutFmtNode = pOldMod;
1000 bool MSWord_SdrAttrIter::IsTxtAttr(xub_StrLen nSwPos)
1002 for (std::vector<EECharAttrib>::const_iterator i = aTxtAtrArr.begin(); i < aTxtAtrArr.end(); ++i)
1004 if (nSwPos >= i->nStart && nSwPos < i->nEnd)
1006 if (i->pAttr->Which() == EE_FEATURE_FIELD ||
1007 i->pAttr->Which() == EE_FEATURE_TAB)
1008 return true;
1011 return false;
1014 // HasItem ist fuer die Zusammenfassung des Doppel-Attributes Underline
1015 // und WordLineMode als TextItems. OutAttr() ruft die Ausgabefunktion,
1016 // die dann ueber HasItem() nach anderen Items an der
1017 // Attribut-Anfangposition fragen kann.
1018 // Es koennen nur Attribute mit Ende abgefragt werden.
1019 // Es wird mit bDeep gesucht
1020 const SfxPoolItem* MSWord_SdrAttrIter::HasTextItem(sal_uInt16 nWhich) const
1022 nWhich = sw::hack::TransformWhichBetweenPools(*pEditPool,
1023 m_rExport.pDoc->GetAttrPool(), nWhich);
1024 if (nWhich)
1026 for (std::vector<EECharAttrib>::const_iterator i = aTxtAtrArr.begin(); i < aTxtAtrArr.end(); ++i)
1028 if (nWhich == i->pAttr->Which() && nTmpSwPos >= i->nStart && nTmpSwPos < i->nEnd)
1029 return i->pAttr; // Found
1030 else if (nTmpSwPos < i->nStart)
1031 return NULL; // dann kommt da nichts mehr
1034 return NULL;
1037 const SfxPoolItem& MSWord_SdrAttrIter::GetItem( sal_uInt16 nWhich ) const
1039 using sw::hack::GetSetWhichFromSwDocWhich;
1040 const SfxPoolItem* pRet = HasTextItem(nWhich);
1041 if (!pRet)
1043 SfxItemSet aSet(pEditObj->GetParaAttribs(nPara));
1044 nWhich = GetSetWhichFromSwDocWhich(aSet, *m_rExport.pDoc, nWhich);
1045 OSL_ENSURE(nWhich, "Impossible, catastrophic failure imminent");
1046 pRet = &aSet.Get(nWhich);
1048 return *pRet;
1051 void MSWord_SdrAttrIter::OutParaAttr(bool bCharAttr)
1053 SfxItemSet aSet( pEditObj->GetParaAttribs( nPara ));
1054 if( aSet.Count() )
1056 const SfxItemSet* pOldSet = m_rExport.GetCurItemSet();
1057 m_rExport.SetCurItemSet( &aSet );
1059 SfxItemIter aIter( aSet );
1060 const SfxPoolItem* pItem = aIter.GetCurItem();
1062 const SfxItemPool* pSrcPool = pEditPool,
1063 * pDstPool = &m_rExport.pDoc->GetAttrPool();
1065 do {
1066 sal_uInt16 nWhich = pItem->Which(),
1067 nSlotId = pSrcPool->GetSlotId( nWhich );
1069 if ( nSlotId && nWhich != nSlotId &&
1070 0 != ( nWhich = pDstPool->GetWhich( nSlotId ) ) &&
1071 nWhich != nSlotId &&
1072 ( bCharAttr ? ( nWhich >= RES_CHRATR_BEGIN && nWhich < RES_TXTATR_END )
1073 : ( nWhich >= RES_PARATR_BEGIN && nWhich < RES_FRMATR_END ) ) )
1075 // use always the SW-Which Id !
1076 SfxPoolItem* pI = pItem->Clone();
1077 pI->SetWhich( nWhich );
1078 if (m_rExport.CollapseScriptsforWordOk(nScript,nWhich))
1079 m_rExport.AttrOutput().OutputItem( *pI );
1080 delete pI;
1082 } while( !aIter.IsAtEnd() && 0 != ( pItem = aIter.NextItem() ) );
1083 m_rExport.SetCurItemSet( pOldSet );
1087 void WW8Export::WriteSdrTextObj(const SdrObject& rObj, sal_uInt8 nTyp)
1089 const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, &rObj);
1090 OSL_ENSURE(pTxtObj, "That is no SdrTextObj!");
1091 if (!pTxtObj)
1092 return;
1094 const OutlinerParaObject* pParaObj = 0;
1095 bool bOwnParaObj = false;
1098 #i13885#
1099 When the object is actively being edited, that text is not set into
1100 the objects normal text object, but lives in a separate object.
1102 if (pTxtObj->IsTextEditActive())
1104 pParaObj = pTxtObj->GetEditOutlinerParaObject();
1105 bOwnParaObj = true;
1107 else
1109 pParaObj = pTxtObj->GetOutlinerParaObject();
1112 if( pParaObj )
1114 WriteOutliner(*pParaObj, nTyp);
1115 if( bOwnParaObj )
1116 delete pParaObj;
1120 void WW8Export::WriteOutliner(const OutlinerParaObject& rParaObj, sal_uInt8 nTyp)
1122 bool bAnyWrite = false;
1123 const EditTextObject& rEditObj = rParaObj.GetTextObject();
1124 MSWord_SdrAttrIter aAttrIter( *this, rEditObj, nTyp );
1126 sal_Int32 nPara = rEditObj.GetParagraphCount();
1127 sal_uInt8 bNul = 0;
1128 for( sal_Int32 n = 0; n < nPara; ++n )
1130 if( n )
1131 aAttrIter.NextPara( n );
1133 rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet();
1135 OSL_ENSURE( pO->empty(), " pO ist am Zeilenanfang nicht leer" );
1137 String aStr( rEditObj.GetText( n ));
1138 xub_StrLen nAktPos = 0;
1139 xub_StrLen nEnd = aStr.Len();
1140 do {
1141 xub_StrLen nNextAttr = aAttrIter.WhereNext();
1142 rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet();
1144 if( nNextAttr > nEnd )
1145 nNextAttr = nEnd;
1147 bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
1148 if( !bTxtAtr )
1149 OutSwString( aStr, nAktPos, nNextAttr - nAktPos,
1150 true, eChrSet );
1152 // Am Zeilenende werden die Attribute bis ueber das CR
1153 // aufgezogen. Ausnahme: Fussnoten am Zeilenende
1154 if( nNextAttr == nEnd && !bTxtAtr )
1155 WriteCR(); // CR danach
1157 // Ausgabe der Zeichenattribute
1158 aAttrIter.OutAttr( nAktPos ); // nAktPos - 1 ??
1159 pChpPlc->AppendFkpEntry( Strm().Tell(),
1160 pO->size(), pO->data() );
1161 pO->clear();
1163 // Ausnahme: Fussnoten am Zeilenende
1164 if( nNextAttr == nEnd && bTxtAtr )
1165 WriteCR(); // CR danach
1166 nAktPos = nNextAttr;
1167 eChrSet = eNextChrSet;
1168 aAttrIter.NextPos();
1170 while( nAktPos < nEnd );
1172 OSL_ENSURE( pO->empty(), " pO ist am ZeilenEnde nicht leer" );
1174 pO->push_back( bNul ); // Style # as short
1175 pO->push_back( bNul );
1177 aAttrIter.OutParaAttr(false);
1179 sal_uLong nPos = Strm().Tell();
1180 pPapPlc->AppendFkpEntry( Strm().Tell(),
1181 pO->size(), pO->data() );
1182 pO->clear();
1183 pChpPlc->AppendFkpEntry( nPos );
1186 bAnyWrite = 0 != nPara;
1187 if( !bAnyWrite )
1188 WriteStringAsPara( aEmptyStr );
1191 void WinwordAnchoring::WriteData( EscherEx& rEx ) const
1193 //Toplevel groups get their winword extra data attached, and sub elements
1194 //use the defaults
1195 if (rEx.GetGroupLevel() <= 1)
1197 SvStream& rSt = rEx.GetStream();
1198 //The last argument denotes the number of sub properties in this atom
1199 if (mbInline)
1201 rEx.AddAtom(18, DFF_msofbtUDefProp, 3, 3); //Prop id is 0xF122
1202 rSt << (sal_uInt16)0x0390 << sal_uInt32(3);
1203 rSt << (sal_uInt16)0x0392 << sal_uInt32(3);
1204 //This sub property is required to be in the dummy inline frame as
1205 //well
1206 rSt << (sal_uInt16)0x053F << nInlineHack;
1208 else
1210 rEx.AddAtom(24, DFF_msofbtUDefProp, 3, 4 ); //Prop id is 0xF122
1211 rSt << (sal_uInt16)0x038F << mnXAlign;
1212 rSt << (sal_uInt16)0x0390 << mnXRelTo;
1213 rSt << (sal_uInt16)0x0391 << mnYAlign;
1214 rSt << (sal_uInt16)0x0392 << mnYRelTo;
1220 void WW8Export::CreateEscher()
1222 SfxItemState eBackSet = pDoc->GetPageDesc(0).GetMaster().
1223 GetItemState(RES_BACKGROUND);
1224 if (pHFSdrObjs->size() || pSdrObjs->size() || SFX_ITEM_SET == eBackSet)
1226 OSL_ENSURE( !pEscher, "wer hat den Pointer nicht geloescht?" );
1227 SvMemoryStream* pEscherStrm = new SvMemoryStream;
1228 pEscherStrm->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
1229 pEscher = new SwEscherEx(pEscherStrm, *this);
1233 void WW8Export::WriteEscher()
1235 if (pEscher)
1237 sal_uLong nStart = pTableStrm->Tell();
1239 pEscher->WritePictures();
1240 pEscher->FinishEscher();
1242 pFib->fcDggInfo = nStart;
1243 pFib->lcbDggInfo = pTableStrm->Tell() - nStart;
1244 delete pEscher, pEscher = 0;
1248 void SwEscherEx::WritePictures()
1250 if( SvStream* pPicStrm = static_cast< SwEscherExGlobal& >( *mxGlobal ).GetPictureStream() )
1252 // set the blip - entries to the correct stream pos
1253 sal_Int32 nEndPos = rWrt.Strm().Tell();
1254 mxGlobal->SetNewBlipStreamOffset( nEndPos );
1256 pPicStrm->Seek( 0 );
1257 rWrt.Strm() << *pPicStrm;
1259 Flush();
1263 // Output- Routines for Escher Export
1265 SwEscherExGlobal::SwEscherExGlobal()
1269 SwEscherExGlobal::~SwEscherExGlobal()
1273 SvStream* SwEscherExGlobal::ImplQueryPictureStream()
1275 // this function will be called exactly once
1276 mxPicStrm.reset( new SvMemoryStream );
1277 mxPicStrm->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
1278 return mxPicStrm.get();
1281 SwBasicEscherEx::SwBasicEscherEx(SvStream* pStrm, WW8Export& rWW8Wrt)
1282 : EscherEx( EscherExGlobalRef( new SwEscherExGlobal ), pStrm), rWrt(rWW8Wrt), pEscherStrm(pStrm)
1284 Init();
1287 SwBasicEscherEx::~SwBasicEscherEx()
1291 void SwBasicEscherEx::WriteFrmExtraData(const SwFrmFmt&)
1293 AddAtom(4, ESCHER_ClientAnchor);
1294 GetStream() << (sal_uInt32)0x80000000;
1297 void SwBasicEscherEx::WriteEmptyFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId)
1299 OpenContainer(ESCHER_SpContainer);
1300 AddShape(ESCHER_ShpInst_PictureFrame, 0xa00, nShapeId);
1301 // store anchor attribute
1302 WriteFrmExtraData(rFmt);
1304 AddAtom(6, DFF_msofbtUDefProp, 3, 1); //Prop id is 0xF122
1305 GetStream() << (sal_uInt16)0x053F << nInlineHack;
1307 CloseContainer(); // ESCHER_SpContainer
1310 sal_uInt32 AddMirrorFlags(sal_uInt32 nFlags, const SwMirrorGrf &rMirror)
1312 switch (rMirror.GetValue())
1314 default:
1315 case RES_MIRROR_GRAPH_DONT:
1316 break;
1317 case RES_MIRROR_GRAPH_VERT:
1318 nFlags |= SHAPEFLAG_FLIPH;
1319 break;
1320 case RES_MIRROR_GRAPH_HOR:
1321 nFlags |= SHAPEFLAG_FLIPV;
1322 break;
1323 case RES_MIRROR_GRAPH_BOTH:
1324 nFlags |= SHAPEFLAG_FLIPH;
1325 nFlags |= SHAPEFLAG_FLIPV;
1326 break;
1329 return nFlags;
1331 //For i120928,this function is added to export graphic of bullet
1332 sal_Int32 SwBasicEscherEx::WriteGrfBullet(const Graphic& rGrf)
1334 OpenContainer( ESCHER_SpContainer );
1335 AddShape(ESCHER_ShpInst_PictureFrame, 0xa00,0x401);
1336 EscherPropertyContainer aPropOpt;
1337 GraphicObject aGraphicObject( rGrf );
1338 OString aUniqueId = aGraphicObject.GetUniqueID();
1339 if ( !aUniqueId.isEmpty() )
1341 const MapMode aMap100mm( MAP_100TH_MM );
1342 Size aSize( rGrf.GetPrefSize() );
1343 if ( MAP_PIXEL == rGrf.GetPrefMapMode().GetMapUnit() )
1345 aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMap100mm );
1347 else
1349 aSize = OutputDevice::LogicToLogic( aSize,rGrf.GetPrefMapMode(), aMap100mm );
1351 Point aEmptyPoint = Point();
1352 Rectangle aRect( aEmptyPoint, aSize );
1353 sal_uInt32 nBlibId = mxGlobal->GetBlibID( *(mxGlobal->QueryPictureStream()), aUniqueId,aRect, NULL, 0 );
1354 if (nBlibId)
1355 aPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, sal_True);
1357 aPropOpt.AddOpt( ESCHER_Prop_pibFlags, ESCHER_BlipFlagDefault );
1358 aPropOpt.AddOpt( ESCHER_Prop_dyTextTop, DrawModelToEmu(0));
1359 aPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, DrawModelToEmu(0));
1360 aPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, DrawModelToEmu(0));
1361 aPropOpt.AddOpt( ESCHER_Prop_dxTextRight, DrawModelToEmu(0));
1362 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
1363 aPropOpt.AddOpt( ESCHER_Prop_dyTextTop, 0 );
1364 aPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, 0 );
1365 aPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, 0 );
1366 aPropOpt.AddOpt( ESCHER_Prop_dxTextRight, 0 );
1367 const Color aTmpColor( COL_WHITE );
1368 SvxBrushItem aBrush( aTmpColor, RES_BACKGROUND );
1369 const SvxBrushItem *pRet = rWrt.GetCurrentPageBgBrush();
1370 if (pRet && (pRet->GetGraphic() ||( pRet->GetColor() != COL_TRANSPARENT)))
1371 aBrush = *pRet;
1372 WriteBrushAttr(aBrush, aPropOpt);
1374 aPropOpt.AddOpt( ESCHER_Prop_pictureActive, 0 );
1375 aPropOpt.Commit( GetStream() );
1376 AddAtom(4, ESCHER_ClientAnchor);
1377 GetStream() << (sal_uInt32)0x80000000;
1378 CloseContainer();
1380 return 0;
1383 sal_Int32 SwBasicEscherEx::WriteGrfFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId)
1385 sal_Int32 nBorderThick=0;
1386 SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(rFmt);
1387 SwGrfNode *pGrfNd = pNd ? pNd->GetGrfNode() : 0;
1388 OSL_ENSURE(pGrfNd, "No SwGrfNode ?, suspicious");
1389 if (!pGrfNd)
1390 return nBorderThick;
1392 OpenContainer( ESCHER_SpContainer );
1394 const SwMirrorGrf &rMirror = pGrfNd->GetSwAttrSet().GetMirrorGrf();
1395 AddShape(ESCHER_ShpInst_PictureFrame, AddMirrorFlags(0xa00, rMirror),
1396 nShapeId);
1398 EscherPropertyContainer aPropOpt;
1400 sal_uInt32 nFlags = ESCHER_BlipFlagDefault;
1402 if (pGrfNd->IsLinkedFile())
1404 String sURL;
1405 pGrfNd->GetFileFilterNms( &sURL, 0 );
1407 ww::bytes aBuf;
1408 SwWW8Writer::InsAsString16( aBuf, sURL );
1409 SwWW8Writer::InsUInt16( aBuf, 0 );
1411 sal_uInt16 nArrLen = aBuf.size();
1412 sal_uInt8* pArr = new sal_uInt8[ nArrLen ];
1413 std::copy( aBuf.begin(), aBuf.end(), pArr);
1415 aPropOpt.AddOpt(ESCHER_Prop_pibName, true, nArrLen, pArr, nArrLen);
1416 nFlags = ESCHER_BlipFlagLinkToFile | ESCHER_BlipFlagURL |
1417 ESCHER_BlipFlagDoNotSave;
1419 else
1421 pGrfNd->SwapIn(true);
1423 Graphic aGraphic(pGrfNd->GetGrf());
1424 GraphicObject aGraphicObject( aGraphic );
1425 OString aUniqueId = aGraphicObject.GetUniqueID();
1427 if (!aUniqueId.isEmpty())
1429 const MapMode aMap100mm( MAP_100TH_MM );
1430 Size aSize( aGraphic.GetPrefSize() );
1432 if ( MAP_PIXEL == aGraphic.GetPrefMapMode().GetMapUnit() )
1434 aSize = Application::GetDefaultDevice()->PixelToLogic(
1435 aSize, aMap100mm );
1437 else
1439 aSize = OutputDevice::LogicToLogic( aSize,
1440 aGraphic.GetPrefMapMode(), aMap100mm );
1443 Point aEmptyPoint = Point();
1444 Rectangle aRect( aEmptyPoint, aSize );
1446 sal_uInt32 nBlibId = mxGlobal->GetBlibID( *QueryPictureStream(),
1447 aUniqueId, aRect, NULL, 0 );
1448 if (nBlibId)
1449 aPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, sal_True);
1453 aPropOpt.AddOpt( ESCHER_Prop_pibFlags, nFlags );
1454 nBorderThick = WriteFlyFrameAttr(rFmt,mso_sptPictureFrame,aPropOpt);
1455 WriteGrfAttr(*pGrfNd, aPropOpt);
1457 aPropOpt.Commit( GetStream() );
1459 // store anchor attribute
1460 WriteFrmExtraData( rFmt );
1462 CloseContainer(); // ESCHER_SpContainer
1463 return nBorderThick;
1466 void SwBasicEscherEx::WriteGrfAttr(const SwNoTxtNode& rNd,
1467 EscherPropertyContainer& rPropOpt)
1469 const SfxPoolItem* pItem;
1470 sal_uInt32 nMode = GRAPHICDRAWMODE_STANDARD;
1471 sal_Int32 nContrast = 0;
1472 sal_Int16 nBrightness = 0;
1474 if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_CONTRAST,
1475 true, &pItem))
1477 nContrast = ((SfxInt16Item*)pItem)->GetValue();
1480 if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_LUMINANCE,
1481 true, &pItem))
1483 nBrightness = ((SfxInt16Item*)pItem)->GetValue();
1487 if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_DRAWMODE,
1488 true, &pItem))
1490 nMode = ((SfxEnumItem*)pItem)->GetValue();
1491 if (nMode == GRAPHICDRAWMODE_WATERMARK)
1494 There is no real watermark mode in word, we must use standard
1495 mode and modify our ones by 70% extra brightness and 70% less
1496 contrast. This means that unmodified default OOo watermark
1497 will turn back into watermark, and modified OOo watermark will
1498 change into a close visual representation in standardmode
1500 nBrightness += 70;
1501 if (nBrightness > 100)
1502 nBrightness = 100;
1503 nContrast -= 70;
1504 if (nContrast < -100)
1505 nContrast = -100;
1506 nMode = GRAPHICDRAWMODE_STANDARD;
1510 if (nMode == GRAPHICDRAWMODE_GREYS)
1511 nMode = 0x40004;
1512 else if (nMode == GRAPHICDRAWMODE_MONO)
1513 nMode = 0x60006;
1514 else
1515 nMode = 0;
1516 rPropOpt.AddOpt( ESCHER_Prop_pictureActive, nMode );
1518 if (nContrast != 0)
1520 nContrast+=100;
1521 if (nContrast == 100)
1522 nContrast = 0x10000;
1523 else if (nContrast < 100)
1525 nContrast *= 0x10000;
1526 nContrast /= 100;
1528 else if (nContrast < 200)
1529 nContrast = (100 * 0x10000) / (200-nContrast);
1530 else
1531 nContrast = 0x7fffffff;
1532 rPropOpt.AddOpt( ESCHER_Prop_pictureContrast, nContrast);
1535 if (nBrightness != 0)
1536 rPropOpt.AddOpt( ESCHER_Prop_pictureBrightness, nBrightness * 327 );
1538 if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_CROPGRF,
1539 true, &pItem))
1541 const Size aSz( rNd.GetTwipSize() );
1542 sal_Int32 nVal;
1543 if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetLeft() ) )
1544 rPropOpt.AddOpt( ESCHER_Prop_cropFromLeft, ToFract16( nVal, aSz.Width()) );
1545 if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetRight() ) )
1546 rPropOpt.AddOpt( ESCHER_Prop_cropFromRight, ToFract16( nVal, aSz.Width()));
1547 if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetTop() ) )
1548 rPropOpt.AddOpt( ESCHER_Prop_cropFromTop, ToFract16( nVal, aSz.Height()));
1549 if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetBottom() ) )
1550 rPropOpt.AddOpt( ESCHER_Prop_cropFromBottom, ToFract16( nVal, aSz.Height()));
1554 void SwBasicEscherEx::SetPicId(const SdrObject &, sal_uInt32,
1555 EscherPropertyContainer &)
1559 void SwEscherEx::SetPicId(const SdrObject &rSdrObj, sal_uInt32 nShapeId,
1560 EscherPropertyContainer &rPropOpt)
1562 pTxtBxs->Append(rSdrObj, nShapeId);
1563 sal_uInt32 nPicId = pTxtBxs->Count();
1564 nPicId *= 0x10000;
1565 rPropOpt.AddOpt( ESCHER_Prop_pictureId, nPicId );
1568 sal_Int32 SwBasicEscherEx::WriteOLEFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId)
1570 sal_Int32 nBorderThick = 0;
1571 if (const SdrObject* pSdrObj = rFmt.FindRealSdrObject())
1573 SwNodeIndex aIdx(*rFmt.GetCntnt().GetCntntIdx(), 1);
1574 SwOLENode& rOLENd = *aIdx.GetNode().GetOLENode();
1575 sal_Int64 nAspect = rOLENd.GetAspect();
1577 uno::Reference < embed::XEmbeddedObject > xObj(rOLENd.GetOLEObj().GetOleRef());
1579 // the rectangle is used to transport the size of the object
1580 // the left, top corner is set to ( 0, 0 ) by default constructor,
1581 // if the width and height are set correctly bRectIsSet should be set to true
1582 awt::Rectangle aRect;
1583 bool bRectIsSet = false;
1586 // TODO/LATER: should the icon size be stored in case of iconified object?
1587 if ( xObj.is() && nAspect != embed::Aspects::MSOLE_ICON )
1591 awt::Size aSize = xObj->getVisualAreaSize( nAspect );
1592 aRect.Width = aSize.Width;
1593 aRect.Height = aSize.Height;
1594 bRectIsSet = true;
1596 catch( const uno::Exception& )
1601 #i5970#
1602 Export floating ole2 .doc ver 8+ wmf ole2 previews as emf previews
1603 instead ==> allows unicode text to be preserved
1605 #ifdef OLE_PREVIEW_AS_EMF
1606 const Graphic* pGraphic = rOLENd.GetGraphic();
1607 #endif
1608 OpenContainer(ESCHER_SpContainer);
1610 EscherPropertyContainer aPropOpt;
1611 const SwMirrorGrf &rMirror = rOLENd.GetSwAttrSet().GetMirrorGrf();
1612 WriteOLEPicture(aPropOpt, AddMirrorFlags(0xa00 | SHAPEFLAG_OLESHAPE,
1613 rMirror), pGraphic ? *pGraphic : Graphic(), *pSdrObj, nShapeId, bRectIsSet ? &aRect : NULL );
1615 nBorderThick = WriteFlyFrameAttr(rFmt, mso_sptPictureFrame, aPropOpt);
1616 WriteGrfAttr(rOLENd, aPropOpt);
1617 aPropOpt.Commit(GetStream());
1619 // store anchor attribute
1620 WriteFrmExtraData( rFmt );
1622 CloseContainer(); // ESCHER_SpContainer
1624 return nBorderThick;
1627 void SwBasicEscherEx::WriteBrushAttr(const SvxBrushItem &rBrush,
1628 EscherPropertyContainer& rPropOpt)
1630 bool bSetOpacity = false;
1631 sal_uInt32 nOpaque = 0;
1632 if (const GraphicObject *pGraphicObject = rBrush.GetGraphicObject())
1634 OString aUniqueId = pGraphicObject->GetUniqueID();
1635 if (!aUniqueId.isEmpty())
1637 const Graphic &rGraphic = pGraphicObject->GetGraphic();
1638 Size aSize(rGraphic.GetPrefSize());
1639 const MapMode aMap100mm(MAP_100TH_MM);
1640 if (MAP_PIXEL == rGraphic.GetPrefMapMode().GetMapUnit())
1642 aSize = Application::GetDefaultDevice()->PixelToLogic(
1643 aSize, aMap100mm);
1645 else
1647 aSize = OutputDevice::LogicToLogic(aSize,
1648 rGraphic.GetPrefMapMode(), aMap100mm);
1651 Point aEmptyPoint = Point();
1652 Rectangle aRect(aEmptyPoint, aSize);
1654 sal_uInt32 nBlibId = mxGlobal->GetBlibID( *QueryPictureStream(),
1655 aUniqueId, aRect, NULL, 0);
1656 if (nBlibId)
1657 rPropOpt.AddOpt(ESCHER_Prop_fillBlip,nBlibId,sal_True);
1660 if (0 != (nOpaque = pGraphicObject->GetAttr().GetTransparency()))
1661 bSetOpacity = true;
1663 rPropOpt.AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
1664 rPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
1665 rPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0 );
1667 else
1669 sal_uInt32 nFillColor = GetColor(rBrush.GetColor(), false);
1670 rPropOpt.AddOpt( ESCHER_Prop_fillColor, nFillColor );
1671 rPropOpt.AddOpt( ESCHER_Prop_fillBackColor, nFillColor ^ 0xffffff );
1672 rPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100010 );
1674 if (0 != (nOpaque = rBrush.GetColor().GetTransparency()))
1675 bSetOpacity = true;
1678 if (bSetOpacity)
1680 nOpaque = (nOpaque * 100) / 0xFE;
1681 nOpaque = ((100 - nOpaque) << 16) / 100;
1682 rPropOpt.AddOpt(ESCHER_Prop_fillOpacity, nOpaque);
1686 static bool lcl_isInHeader(const SwFrmFmt& rFmt)
1688 const SwFlyFrmFmt* pFlyFrmFmt = dynamic_cast<const SwFlyFrmFmt*>(&rFmt);
1689 if (!pFlyFrmFmt)
1690 return false;
1691 SwFlyFrm* pFlyFrm = const_cast<SwFlyFrm*>(pFlyFrmFmt->GetFrm());
1692 if (!pFlyFrm) // fdo#54648: "hidden" drawing object has no layout frame
1694 return false;
1696 SwPageFrm* pPageFrm = pFlyFrm->FindPageFrmOfAnchor();
1697 SwFrm* pHeader = pPageFrm->Lower();
1698 if (pHeader->GetType() == FRM_HEADER)
1700 const SwFrm* pFrm = pFlyFrm->GetAnchorFrm();
1701 while (pFrm)
1703 if (pFrm == pHeader)
1704 return true;
1705 pFrm = pFrm->GetUpper();
1708 return false;
1711 sal_Int32 SwBasicEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt,
1712 MSO_SPT eShapeType, EscherPropertyContainer& rPropOpt)
1714 sal_Int32 nLineWidth=0;
1715 const SfxPoolItem* pItem;
1716 bool bFirstLine = true;
1717 if (SFX_ITEM_SET == rFmt.GetItemState(RES_BOX, true, &pItem))
1719 static const sal_uInt16 aExhperProp[4] =
1721 ESCHER_Prop_dyTextTop, ESCHER_Prop_dyTextBottom,
1722 ESCHER_Prop_dxTextLeft, ESCHER_Prop_dxTextRight
1724 const SvxBorderLine* pLine;
1726 for( sal_uInt16 n = 0; n < 4; ++n )
1727 if( 0 != ( pLine = ((SvxBoxItem*)pItem)->GetLine( n )) )
1729 if( bFirstLine )
1731 sal_uInt32 nLineColor = GetColor(pLine->GetColor(), false);
1732 rPropOpt.AddOpt( ESCHER_Prop_lineColor, nLineColor );
1733 rPropOpt.AddOpt( ESCHER_Prop_lineBackColor,
1734 nLineColor ^ 0xffffff );
1736 MSO_LineStyle eStyle;
1737 if( pLine->isDouble() )
1739 // double line
1740 nLineWidth = pLine->GetWidth();
1741 if( pLine->GetInWidth() == pLine->GetOutWidth() )
1742 eStyle = mso_lineDouble;
1743 else if( pLine->GetInWidth() < pLine->GetOutWidth() )
1744 eStyle = mso_lineThickThin;
1745 else
1746 eStyle = mso_lineThinThick;
1748 else
1750 // simple line
1751 eStyle = mso_lineSimple;
1752 nLineWidth = pLine->GetWidth();
1755 rPropOpt.AddOpt( ESCHER_Prop_lineStyle, eStyle );
1756 rPropOpt.AddOpt( ESCHER_Prop_lineWidth,
1757 DrawModelToEmu( nLineWidth ));
1759 MSO_LineDashing eDashing = mso_lineSolid;
1760 switch (pLine->GetBorderLineStyle())
1762 case table::BorderLineStyle::DASHED:
1763 eDashing = mso_lineDashGEL;
1764 break;
1765 case table::BorderLineStyle::DOTTED:
1766 eDashing = mso_lineDotGEL;
1767 break;
1768 case table::BorderLineStyle::SOLID:
1769 default:
1770 break;
1772 rPropOpt.AddOpt( ESCHER_Prop_lineDashing, eDashing );
1773 rPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x8000E );
1775 //Use import logic to determine how much of border will go
1776 //outside graphic
1777 nLineWidth = SwMSDffManager::GetEscherLineMatch(
1778 eStyle,eShapeType,nLineWidth);
1779 bFirstLine = false;
1781 rPropOpt.AddOpt( aExhperProp[ n ], DrawModelToEmu(
1782 ((SvxBoxItem*)pItem)->GetDistance( n ) ));
1784 else
1785 // MM If there is no line the distance should be set to 0
1786 rPropOpt.AddOpt( aExhperProp[ n ], DrawModelToEmu(0));
1788 if( bFirstLine ) // no valid line found
1790 rPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
1791 rPropOpt.AddOpt( ESCHER_Prop_dyTextTop, 0 );
1792 rPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, 0 );
1793 rPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, 0 );
1794 rPropOpt.AddOpt( ESCHER_Prop_dxTextRight, 0 );
1797 // SwWW8ImplReader::Read_GrafLayer() imports these as opaque
1798 // unconditionally, so if both are true, don't export the property.
1799 bool bIsInHeader = lcl_isInHeader(rFmt);
1800 bool bIsThrought = rFmt.GetSurround().GetValue() == SURROUND_THROUGHT;
1802 if (bIsInHeader)
1804 const SvxBrushItem& rBrush(rFmt.GetBackground());
1805 WriteBrushAttr(rBrush, rPropOpt);
1807 else
1809 SvxBrushItem aBrush(rWrt.TrueFrameBgBrush(rFmt));
1810 WriteBrushAttr(aBrush, rPropOpt);
1813 const SdrObject* pObj = rFmt.FindRealSdrObject();
1815 if( pObj && (pObj->GetLayer() == GetHellLayerId() ||
1816 pObj->GetLayer() == GetInvisibleHellId() ) && !(bIsInHeader && bIsThrought))
1818 rPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 );
1821 return nLineWidth;
1824 sal_Int32 SwEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt, MSO_SPT eShapeType,
1825 EscherPropertyContainer& rPropOpt)
1827 sal_Int32 nLineWidth = SwBasicEscherEx::WriteFlyFrameAttr(rFmt, eShapeType,
1828 rPropOpt);
1831 These are not in SwBasicEscherEx::WriteFlyFrameAttr because inline objs
1832 can't do it in word and it hacks it in by stretching the graphic that
1833 way, perhaps we should actually draw in this space into the graphic we
1834 are exporting!
1836 const SfxPoolItem* pItem;
1837 if (SFX_ITEM_SET == rFmt.GetItemState(RES_LR_SPACE, true, &pItem))
1839 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft,
1840 DrawModelToEmu( ((SvxLRSpaceItem*)pItem)->GetLeft() ) );
1841 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight,
1842 DrawModelToEmu( ((SvxLRSpaceItem*)pItem)->GetRight() ) );
1844 else
1846 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft, 0 );
1847 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight, 0 );
1850 if (SFX_ITEM_SET == rFmt.GetItemState(RES_UL_SPACE, true, &pItem))
1852 rPropOpt.AddOpt( ESCHER_Prop_dyWrapDistTop,
1853 DrawModelToEmu( ((SvxULSpaceItem*)pItem)->GetUpper() ) );
1854 rPropOpt.AddOpt( ESCHER_Prop_dyWrapDistBottom,
1855 DrawModelToEmu( ((SvxULSpaceItem*)pItem)->GetLower() ) );
1858 if (rFmt.GetSurround().IsContour())
1860 if (const SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(rFmt))
1862 const PolyPolygon *pPolyPoly = pNd->HasContour();
1863 if (pPolyPoly && pPolyPoly->Count())
1865 Polygon aPoly(PolygonFromPolyPolygon(*pPolyPoly));
1866 const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
1867 Fraction aMapPolyX(ww::nWrap100Percent, rOrigSize.Width());
1868 Fraction aMapPolyY(ww::nWrap100Percent, rOrigSize.Height());
1869 aPoly.Scale(aMapPolyX, aMapPolyY);
1872 a) stretch right bound by 15twips
1873 b) shrink bottom bound to where it would have been in word
1874 c) Move it to the left by 15twips
1876 See the import for details
1878 const Size &rSize = pNd->GetTwipSize();
1879 Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
1880 aMoveHack *= Fraction(15, 1);
1881 long nMove(aMoveHack);
1883 Fraction aHackX(ww::nWrap100Percent + nMove,
1884 ww::nWrap100Percent);
1885 Fraction aHackY(ww::nWrap100Percent - nMove,
1886 ww::nWrap100Percent);
1887 aPoly.Scale(aHackX, aHackY);
1889 aPoly.Move(-nMove, 0);
1891 SvMemoryStream aPolyDump;
1892 aPolyDump.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
1894 sal_uInt16 nLen = aPoly.GetSize();
1895 aPolyDump << nLen;
1896 aPolyDump << nLen;
1897 aPolyDump << sal_uInt16(8);
1898 for (sal_uInt16 nI = 0; nI < nLen; ++nI)
1900 aPolyDump << sal_uInt32(aPoly[nI].X());
1901 aPolyDump << sal_uInt32(aPoly[nI].Y());
1904 sal_uInt16 nArrLen = msword_cast<sal_uInt16>(aPolyDump.Tell());
1905 void *pArr = const_cast<void *>(aPolyDump.GetData());
1906 //PropOpt wants to own the buffer
1907 aPolyDump.ObjectOwnsMemory(false);
1908 rPropOpt.AddOpt(DFF_Prop_pWrapPolygonVertices, false,
1909 nArrLen, static_cast<sal_uInt8 *>(pArr), nArrLen);
1914 return nLineWidth;
1917 void SwBasicEscherEx::Init()
1919 MapUnit eMap = MAP_TWIP;
1920 if (SdrModel *pModel = rWrt.pDoc->GetDrawModel())
1922 // PPT arbeitet nur mit Einheiten zu 576DPI
1923 // WW hingegen verwendet twips, dh. 1440DPI.
1924 eMap = pModel->GetScaleUnit();
1927 // MS-DFF-Properties sind grossteils in EMU (English Metric Units) angegeben
1928 // 1mm=36000emu, 1twip=635emu
1929 Fraction aFact(360, 1);
1930 aFact /= GetMapFactor(MAP_100TH_MM, eMap).X();
1931 // create little values
1932 aFact = Fraction(aFact.GetNumerator(), aFact.GetDenominator());
1933 mnEmuMul = aFact.GetNumerator();
1934 mnEmuDiv = aFact.GetDenominator();
1936 SetHellLayerId(rWrt.pDoc->GetHellId());
1939 sal_Int32 SwBasicEscherEx::ToFract16(sal_Int32 nVal, sal_uInt32 nMax) const
1941 if (nMax)
1943 sal_Int32 nMSVal = (nVal / 65536) * nMax;
1944 nMSVal += (nVal * 65536 ) / nMax;
1945 return nMSVal;
1947 return 0;
1950 SdrLayerID SwBasicEscherEx::GetInvisibleHellId() const
1952 return rWrt.pDoc->GetInvisibleHellId();
1955 void SwBasicEscherEx::WritePictures()
1957 if( SvStream* pPicStrm = static_cast< SwEscherExGlobal& >( *mxGlobal ).GetPictureStream() )
1959 // set the blip - entries to the correct stream pos
1960 sal_Int32 nEndPos = pPicStrm->Tell();
1961 mxGlobal->WriteBlibStoreEntry(*pEscherStrm, 1, sal_True, nEndPos);
1963 pPicStrm->Seek(0);
1964 *pEscherStrm << *pPicStrm;
1968 SwEscherEx::SwEscherEx(SvStream* pStrm, WW8Export& rWW8Wrt)
1969 : SwBasicEscherEx(pStrm, rWW8Wrt),
1970 pTxtBxs(0)
1972 aHostData.SetClientData(&aWinwordAnchoring);
1973 OpenContainer( ESCHER_DggContainer );
1975 sal_uInt16 nColorCount = 4;
1976 *pStrm << (sal_uInt16)( nColorCount << 4 ) // instance
1977 << (sal_uInt16)ESCHER_SplitMenuColors // record type
1978 << (sal_uInt32)( nColorCount * 4 ) // size
1979 << (sal_uInt32)0x08000004
1980 << (sal_uInt32)0x08000001
1981 << (sal_uInt32)0x08000002
1982 << (sal_uInt32)0x100000f7;
1984 CloseContainer(); // ESCHER_DggContainer
1986 sal_uInt8 i = 2; // for header/footer and the other
1987 PlcDrawObj *pSdrObjs = rWrt.pHFSdrObjs;
1988 pTxtBxs = rWrt.pHFTxtBxs;
1990 // if no header/footer -> skip over
1991 if (!pSdrObjs->size())
1993 --i;
1994 pSdrObjs = rWrt.pSdrObjs;
1995 pTxtBxs = rWrt.pTxtBxs;
1998 for( ; i--; pSdrObjs = rWrt.pSdrObjs, pTxtBxs = rWrt.pTxtBxs )
2000 // "dummy char" (or any Count ?) - why? This knows only M$
2001 GetStream() << (sal_Char)i;
2003 OpenContainer( ESCHER_DgContainer );
2005 EnterGroup( 0 );
2007 sal_uLong nSecondShapeId = pSdrObjs == rWrt.pSdrObjs ? GenerateShapeId() : 0;
2009 // write now all Writer-/DrawObjects
2010 DrawObjPointerVector aSorted;
2011 MakeZOrderArrAndFollowIds(pSdrObjs->GetObjArr(), aSorted);
2013 sal_uInt32 nShapeId=0;
2014 DrawObjPointerIter aEnd = aSorted.end();
2015 for (DrawObjPointerIter aIter = aSorted.begin(); aIter != aEnd; ++aIter)
2017 sal_Int32 nBorderThick=0;
2018 DrawObj *pObj = (*aIter);
2019 OSL_ENSURE(pObj, "impossible");
2020 if (!pObj)
2021 continue;
2022 const sw::Frame &rFrame = pObj->maCntnt;
2023 const SwFrmFmt& rFmt = rFrame.GetFrmFmt();
2025 switch (rFrame.GetWriterType())
2027 case sw::Frame::eTxtBox:
2028 case sw::Frame::eOle:
2029 case sw::Frame::eGraphic:
2030 nBorderThick = WriteFlyFrm(*pObj, nShapeId, aSorted);
2031 break;
2032 case sw::Frame::eFormControl:
2033 WriteOCXControl(rFmt, nShapeId = GenerateShapeId());
2034 break;
2035 case sw::Frame::eDrawing:
2037 aWinwordAnchoring.SetAnchoring(rFmt);
2038 const SdrObject* pSdrObj = rFmt.FindRealSdrObject();
2039 if (pSdrObj)
2041 bool bSwapInPage = false;
2042 if (!pSdrObj->GetPage())
2044 if (SdrModel* pModel = rWrt.pDoc->GetDrawModel())
2046 if (SdrPage *pPage = pModel->GetPage(0))
2048 bSwapInPage = true;
2049 (const_cast<SdrObject*>(pSdrObj))->SetPage(pPage);
2054 nShapeId = AddSdrObject(*pSdrObj);
2056 if (bSwapInPage)
2057 (const_cast<SdrObject*>(pSdrObj))->SetPage(0);
2059 #if OSL_DEBUG_LEVEL > 0
2060 else
2061 OSL_ENSURE( !this, "Where is the SDR-Object?" );
2062 #endif
2064 break;
2065 default:
2066 break;
2069 if( !nShapeId )
2071 nShapeId = AddDummyShape();
2074 pObj->SetShapeDetails(nShapeId, nBorderThick);
2077 EndSdrObjectPage(); // ???? Bugfix for 74724
2079 if( nSecondShapeId )
2081 OpenContainer( ESCHER_SpContainer );
2083 AddShape( ESCHER_ShpInst_Rectangle, 0xe00, nSecondShapeId );
2085 EscherPropertyContainer aPropOpt;
2086 const SwFrmFmt &rFmt = rWrt.pDoc->GetPageDesc(0).GetMaster();
2087 const SfxPoolItem* pItem = 0;
2088 SfxItemState eState = rFmt.GetItemState(RES_BACKGROUND, true,
2089 &pItem);
2090 if (SFX_ITEM_SET == eState && pItem)
2092 const SvxBrushItem* pBrush = (const SvxBrushItem*)pItem;
2093 WriteBrushAttr(*pBrush, aPropOpt);
2095 SvxGraphicPosition ePos = pBrush->GetGraphicPos();
2096 if( ePos != GPOS_NONE && ePos != GPOS_AREA )
2098 /* #i56806# 0x033F parameter specifies a 32-bit field of shape boolean properties.
2099 0x10001 means fBackground and fUsefBackground flag are true thus background
2100 picture will be shown as "tiled" fill.*/
2101 aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 );
2104 aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x8000001 );
2105 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080008 );
2106 aPropOpt.AddOpt( ESCHER_Prop_shadowColor, 0x8000002 );
2107 aPropOpt.AddOpt( ESCHER_Prop_lineWidth, 0 );
2109 aPropOpt.Commit( *pStrm );
2111 AddAtom( 4, ESCHER_ClientData );
2112 GetStream() << static_cast<sal_Int32>(1);
2114 CloseContainer(); // ESCHER_SpContainer
2116 CloseContainer(); // ESCHER_DgContainer
2120 SwEscherEx::~SwEscherEx()
2124 void SwEscherEx::FinishEscher()
2126 pEscherStrm->Seek(0);
2127 *rWrt.pTableStrm << *pEscherStrm;
2128 delete pEscherStrm, pEscherStrm = 0;
2131 /** method to perform conversion of positioning attributes with the help
2132 of corresponding layout information
2134 #i30669#
2135 Because most of the Writer object positions doesn't correspond to the
2136 object positions in WW8, this method converts the positioning
2137 attributes. For this conversion the corresponding layout information
2138 is needed. If no layout information exists - e.g. no layout exists - no
2139 conversion is performed.
2140 No conversion is performed for as-character anchored objects. Whose
2141 object positions are already treated special in method <WriteData(..)>.
2143 @param _iorHoriOri
2144 input/output parameter - containing the current horizontal position
2145 attributes, which are converted by this method.
2147 @param _iorVertOri
2148 input/output parameter - containing the current vertical position
2149 attributes, which are converted by this method.
2151 @param _rFrmFmt
2152 input parameter - frame format of the anchored object
2154 @return boolean, indicating, if a conversion has been performed.
2156 bool WinwordAnchoring::ConvertPosition( SwFmtHoriOrient& _iorHoriOri,
2157 SwFmtVertOrient& _iorVertOri,
2158 const SwFrmFmt& _rFrmFmt )
2160 const RndStdIds eAnchor = _rFrmFmt.GetAnchor().GetAnchorId();
2162 if ( (FLY_AS_CHAR == eAnchor) || (FLY_AT_FLY == eAnchor) )
2164 // no conversion for as-character or at frame anchored objects
2165 return false;
2168 // determine anchored object
2169 SwAnchoredObject* pAnchoredObj( 0L );
2171 const SwContact* pContact = _rFrmFmt.FindContactObj();
2172 if ( pContact )
2174 std::list<SwAnchoredObject*> aAnchoredObjs;
2175 pContact->GetAnchoredObjs( aAnchoredObjs );
2176 if ( !aAnchoredObjs.empty() )
2178 pAnchoredObj = aAnchoredObjs.front();
2182 if ( !pAnchoredObj )
2184 // no anchored object found. Thus, the needed layout information can't
2185 // be determined. --> no conversion
2186 return false;
2188 // no conversion for anchored drawing object, which aren't attached to an
2189 // anchor frame.
2190 // This is the case for drawing objects, which are anchored inside a page
2191 // header/footer of an *unused* page style.
2192 if ( dynamic_cast<SwAnchoredDrawObject*>(pAnchoredObj) &&
2193 !pAnchoredObj->GetAnchorFrm() )
2195 return false;
2198 bool bConverted( false );
2200 // determine value of attribute 'Follow text flow', because positions aligned
2201 // at page areas have to be converted, if it's set.
2202 const bool bFollowTextFlow = _rFrmFmt.GetFollowTextFlow().GetValue();
2204 // check, if horizontal and vertical position have to be converted due to
2205 // the fact, that the object is anchored at a paragraph, which has a "column
2206 // break before" attribute
2207 bool bConvDueToAnchoredAtColBreakPara( false );
2208 if ( ( (eAnchor == FLY_AT_PARA) || (eAnchor == FLY_AT_CHAR) ) &&
2209 _rFrmFmt.GetAnchor().GetCntntAnchor() &&
2210 _rFrmFmt.GetAnchor().GetCntntAnchor()->nNode.GetNode().IsTxtNode() )
2212 SwTxtNode& rAnchorTxtNode =
2213 dynamic_cast<SwTxtNode&>(_rFrmFmt.GetAnchor().GetCntntAnchor()->nNode.GetNode());
2214 const SvxFmtBreakItem* pBreak = &(ItemGet<SvxFmtBreakItem>(rAnchorTxtNode, RES_BREAK));
2215 if ( pBreak &&
2216 pBreak->GetBreak() == SVX_BREAK_COLUMN_BEFORE )
2218 bConvDueToAnchoredAtColBreakPara = true;
2222 // convert horizontal position, if needed
2224 enum HoriConv { NO_CONV, CONV2PG, CONV2COL, CONV2CHAR };
2225 HoriConv eHoriConv( NO_CONV );
2227 // determine, if conversion has to be performed due to the position orientation
2228 bool bConvDueToOrientation( false );
2230 const sal_Int16 eHOri = _iorHoriOri.GetHoriOrient();
2231 bConvDueToOrientation = eHOri == text::HoriOrientation::LEFT || eHOri == text::HoriOrientation::RIGHT ||
2232 eHOri == text::HoriOrientation::INSIDE || eHOri == text::HoriOrientation::OUTSIDE ||
2233 ( eHOri != text::HoriOrientation::CENTER && _iorHoriOri.IsPosToggle() );
2236 // determine conversion type due to the position relation
2237 if ( bConvDueToAnchoredAtColBreakPara )
2239 eHoriConv = CONV2PG;
2241 else if ( _iorHoriOri.IsPosToggle()
2242 && _iorHoriOri.GetHoriOrient() == text::HoriOrientation::RIGHT )
2244 eHoriConv = NO_CONV;
2245 _iorHoriOri.SetHoriOrient( text::HoriOrientation::OUTSIDE );
2247 else
2249 switch ( _iorHoriOri.GetRelationOrient() )
2251 case text::RelOrientation::PAGE_FRAME:
2252 case text::RelOrientation::PAGE_PRINT_AREA:
2254 if ( bConvDueToOrientation || bFollowTextFlow )
2255 eHoriConv = CONV2PG;
2257 break;
2258 case text::RelOrientation::PAGE_LEFT:
2259 case text::RelOrientation::PAGE_RIGHT:
2261 // relation not supported by WW8. Thus, conversion always needed.
2262 eHoriConv = CONV2PG;
2264 break;
2265 case text::RelOrientation::FRAME:
2267 if ( bConvDueToOrientation )
2268 eHoriConv = CONV2COL;
2270 break;
2271 case text::RelOrientation::PRINT_AREA:
2272 case text::RelOrientation::FRAME_LEFT:
2273 case text::RelOrientation::FRAME_RIGHT:
2275 // relation not supported by WW8. Thus, conversion always needed.
2276 eHoriConv = CONV2COL;
2278 break;
2279 case text::RelOrientation::CHAR:
2281 if ( bConvDueToOrientation )
2282 eHoriConv = CONV2CHAR;
2284 break;
2285 default:
2286 OSL_FAIL( "<WinwordAnchoring::ConvertPosition(..)> - unknown horizontal relation" );
2289 if ( eHoriConv != NO_CONV )
2291 _iorHoriOri.SetHoriOrient( text::HoriOrientation::NONE );
2292 SwTwips nPosX( 0L );
2294 Point aPos;
2295 if ( eHoriConv == CONV2PG )
2297 _iorHoriOri.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
2298 // #i33818#
2299 bool bRelToTableCell( false );
2300 aPos = pAnchoredObj->GetRelPosToPageFrm( bFollowTextFlow,
2301 bRelToTableCell );
2302 if ( bRelToTableCell )
2304 _iorHoriOri.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA );
2307 else if ( eHoriConv == CONV2COL )
2309 _iorHoriOri.SetRelationOrient( text::RelOrientation::FRAME );
2310 aPos = pAnchoredObj->GetRelPosToAnchorFrm();
2312 else if ( eHoriConv == CONV2CHAR )
2314 _iorHoriOri.SetRelationOrient( text::RelOrientation::CHAR );
2315 aPos = pAnchoredObj->GetRelPosToChar();
2317 // No distinction between layout directions, because of missing
2318 // information about WW8 in vertical layout.
2319 nPosX = aPos.X();
2321 _iorHoriOri.SetPos( nPosX );
2322 bConverted = true;
2326 // convert vertical position, if needed
2328 enum VertConv { NO_CONV, CONV2PG, CONV2PARA, CONV2LINE };
2329 VertConv eVertConv( NO_CONV );
2331 // determine, if conversion has to be performed due to the position orientation
2332 bool bConvDueToOrientation( false );
2334 const sal_Int16 eVOri = _iorVertOri.GetVertOrient();
2335 bConvDueToOrientation = ( eVOri == text::VertOrientation::TOP ||
2336 eVOri == text::VertOrientation::BOTTOM ||
2337 eVOri == text::VertOrientation::CHAR_TOP ||
2338 eVOri == text::VertOrientation::CHAR_BOTTOM ||
2339 eVOri == text::VertOrientation::CHAR_CENTER ||
2340 eVOri == text::VertOrientation::LINE_TOP ||
2341 eVOri == text::VertOrientation::LINE_BOTTOM ||
2342 eVOri == text::VertOrientation::LINE_CENTER );
2345 // determine conversion type due to the position relation
2346 if ( bConvDueToAnchoredAtColBreakPara )
2348 eVertConv = CONV2PG;
2350 else
2352 switch ( _iorVertOri.GetRelationOrient() )
2354 case text::RelOrientation::PAGE_FRAME:
2355 case text::RelOrientation::PAGE_PRINT_AREA:
2357 if ( bConvDueToOrientation || bFollowTextFlow )
2358 eVertConv = CONV2PG;
2360 break;
2361 case text::RelOrientation::FRAME:
2363 if ( bConvDueToOrientation ||
2364 _iorVertOri.GetVertOrient() == text::VertOrientation::CENTER )
2366 eVertConv = CONV2PARA;
2369 break;
2370 case text::RelOrientation::PRINT_AREA:
2372 // relation not supported by WW8. Thus, conversion always needed.
2373 eVertConv = CONV2PARA;
2375 break;
2376 case text::RelOrientation::CHAR:
2378 // relation not supported by WW8. Thus, conversion always needed.
2379 eVertConv = CONV2PARA;
2381 break;
2382 case text::RelOrientation::TEXT_LINE:
2384 if ( bConvDueToOrientation ||
2385 _iorVertOri.GetVertOrient() == text::VertOrientation::NONE )
2387 eVertConv = CONV2LINE;
2390 break;
2391 case text::RelOrientation::PAGE_LEFT:
2392 case text::RelOrientation::PAGE_RIGHT:
2393 case text::RelOrientation::FRAME_LEFT:
2394 case text::RelOrientation::FRAME_RIGHT:
2395 default:
2396 OSL_FAIL( "<WinwordAnchoring::ConvertPosition(..)> - unknown vertical relation" );
2400 if ( eVertConv != NO_CONV )
2402 _iorVertOri.SetVertOrient( text::VertOrientation::NONE );
2403 SwTwips nPosY( 0L );
2405 Point aPos;
2406 if ( eVertConv == CONV2PG )
2408 _iorVertOri.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
2409 // #i33818#
2410 bool bRelToTableCell( false );
2411 aPos = pAnchoredObj->GetRelPosToPageFrm( bFollowTextFlow,
2412 bRelToTableCell );
2413 if ( bRelToTableCell )
2415 _iorVertOri.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA );
2418 else if ( eVertConv == CONV2PARA )
2420 _iorVertOri.SetRelationOrient( text::RelOrientation::FRAME );
2421 aPos = pAnchoredObj->GetRelPosToAnchorFrm();
2423 else if ( eVertConv == CONV2LINE )
2425 _iorVertOri.SetRelationOrient( text::RelOrientation::TEXT_LINE );
2426 aPos = pAnchoredObj->GetRelPosToLine();
2428 // No distinction between layout directions, because of missing
2429 // information about WW8 in vertical layout.
2430 nPosY = aPos.Y();
2432 _iorVertOri.SetPos( nPosY );
2433 bConverted = true;
2437 return bConverted;
2440 void WinwordAnchoring::SetAnchoring(const SwFrmFmt& rFmt)
2442 const RndStdIds eAnchor = rFmt.GetAnchor().GetAnchorId();
2443 mbInline = (eAnchor == FLY_AS_CHAR);
2445 SwFmtHoriOrient rHoriOri = rFmt.GetHoriOrient();
2446 SwFmtVertOrient rVertOri = rFmt.GetVertOrient();
2448 // #i30669# - convert the positioning attributes.
2449 // Most positions are converted, if layout information exists.
2450 const bool bPosConverted = ConvertPosition( rHoriOri, rVertOri, rFmt );
2452 const sal_Int16 eHOri = rHoriOri.GetHoriOrient();
2453 const sal_Int16 eVOri = rVertOri.GetVertOrient(); // #i22673#
2455 const sal_Int16 eHRel = rHoriOri.GetRelationOrient();
2456 const sal_Int16 eVRel = rVertOri.GetRelationOrient();
2458 // horizontal Adjustment
2459 switch (eHOri)
2461 default:
2462 case text::HoriOrientation::NONE:
2463 mnXAlign = 0;
2464 break;
2465 case text::HoriOrientation::LEFT:
2466 mnXAlign = 1;
2467 break;
2468 case text::HoriOrientation::CENTER:
2469 mnXAlign = 2;
2470 break;
2471 case text::HoriOrientation::RIGHT:
2472 mnXAlign = 3;
2473 break;
2474 case text::HoriOrientation::INSIDE:
2475 mnXAlign = 4;
2476 break;
2477 case text::HoriOrientation::OUTSIDE:
2478 mnXAlign = 5;
2479 break;
2482 // vertical Adjustment
2483 // #i22673#
2484 // When adjustment is vertically relative to line or to char
2485 // bottom becomes top and vice versa
2486 const bool bVertSwap = !bPosConverted &&
2487 ( (eVRel == text::RelOrientation::CHAR) ||
2488 (eVRel == text::RelOrientation::TEXT_LINE) );
2489 switch (eVOri)
2491 default:
2492 case text::VertOrientation::NONE:
2493 mnYAlign = 0;
2494 break;
2495 case text::VertOrientation::TOP:
2496 case text::VertOrientation::LINE_TOP:
2497 case text::VertOrientation::CHAR_TOP:
2498 mnYAlign = bVertSwap ? 3 : 1;
2499 break;
2500 case text::VertOrientation::CENTER:
2501 case text::VertOrientation::LINE_CENTER:
2502 mnYAlign = 2;
2503 break;
2504 case text::VertOrientation::BOTTOM:
2505 case text::VertOrientation::LINE_BOTTOM:
2506 case text::VertOrientation::CHAR_BOTTOM:
2507 mnYAlign = bVertSwap ? 1 : 3;
2508 break;
2511 // Adjustment is horizontally relative to...
2512 switch (eHRel)
2514 case text::RelOrientation::PAGE_PRINT_AREA:
2515 mnXRelTo = 0;
2516 break;
2517 case text::RelOrientation::PAGE_FRAME:
2518 case text::RelOrientation::PAGE_LEFT: //:-(
2519 case text::RelOrientation::PAGE_RIGHT: //:-(
2520 mnXRelTo = 1;
2521 break;
2522 case text::RelOrientation::FRAME:
2523 case text::RelOrientation::FRAME_LEFT: //:-(
2524 case text::RelOrientation::FRAME_RIGHT: //:-(
2525 if (eAnchor == FLY_AT_PAGE)
2526 mnXRelTo = 1;
2527 else
2528 mnXRelTo = 2;
2529 break;
2530 case text::RelOrientation::PRINT_AREA:
2531 if (eAnchor == FLY_AT_PAGE)
2532 mnXRelTo = 0;
2533 else
2534 mnXRelTo = 2;
2535 break;
2536 case text::RelOrientation::CHAR:
2537 mnXRelTo = 3;
2538 break;
2539 case text::RelOrientation::TEXT_LINE:
2540 break;
2543 // Adjustment is vertically relative to...
2544 switch (eVRel)
2546 case text::RelOrientation::PAGE_PRINT_AREA:
2547 mnYRelTo = 0;
2548 break;
2549 case text::RelOrientation::PAGE_FRAME:
2550 mnYRelTo = 1;
2551 break;
2552 case text::RelOrientation::PRINT_AREA:
2553 if (eAnchor == FLY_AT_PAGE)
2554 mnYRelTo = 0;
2555 else
2556 mnYRelTo = 2;
2557 break;
2558 case text::RelOrientation::FRAME:
2559 if (eAnchor == FLY_AT_PAGE)
2560 mnYRelTo = 1;
2561 else
2562 mnYRelTo = 2;
2563 break;
2564 case text::RelOrientation::CHAR:
2565 case text::RelOrientation::TEXT_LINE: // #i22673# - vertical alignment at top of line
2566 case text::RelOrientation::PAGE_LEFT: //nonsense
2567 case text::RelOrientation::PAGE_RIGHT: //nonsense
2568 case text::RelOrientation::FRAME_LEFT: //nonsense
2569 case text::RelOrientation::FRAME_RIGHT: //nonsense
2570 mnYRelTo = 3;
2571 break;
2575 void SwEscherEx::WriteFrmExtraData( const SwFrmFmt& rFmt )
2577 aWinwordAnchoring.SetAnchoring(rFmt);
2578 aWinwordAnchoring.WriteData(*this);
2580 AddAtom(4, ESCHER_ClientAnchor);
2581 GetStream() << static_cast<sal_Int32>(0);
2583 AddAtom(4, ESCHER_ClientData);
2584 GetStream() << static_cast<sal_Int32>(1);
2587 sal_Int32 SwEscherEx::WriteFlyFrm(const DrawObj &rObj, sal_uInt32 &rShapeId,
2588 DrawObjPointerVector &rPVec)
2590 const SwFrmFmt &rFmt = rObj.maCntnt.GetFrmFmt();
2592 // check for textflyframe and if it is the first in a Chain
2593 sal_Int32 nBorderThick = 0;
2594 const SwNodeIndex* pNdIdx = rFmt.GetCntnt().GetCntntIdx();
2595 if( pNdIdx )
2597 SwNodeIndex aIdx( *pNdIdx, 1 );
2598 switch( aIdx.GetNode().GetNodeType() )
2600 case ND_GRFNODE:
2601 nBorderThick = WriteGrfFlyFrame( rFmt, rShapeId = GenerateShapeId() );
2602 break;
2603 case ND_OLENODE:
2604 nBorderThick = WriteOLEFlyFrame( rFmt, rShapeId = GenerateShapeId() );
2605 break;
2606 default:
2607 if (const SdrObject* pObj = rFmt.FindRealSdrObject())
2609 // check for the first in a Chain
2610 sal_uInt32 nTxtId;
2611 sal_uInt16 nOff = 0;
2612 const SwFrmFmt* pFmt = &rFmt, *pPrev;
2613 while( 0 != ( pPrev = pFmt->GetChain().GetPrev() ))
2615 ++nOff;
2616 pFmt = pPrev;
2619 rShapeId = GetFlyShapeId(rFmt, rObj.mnHdFtIndex, rPVec);
2620 if( !nOff )
2622 nTxtId = pTxtBxs->GetPos( pObj );
2623 if( USHRT_MAX == nTxtId )
2625 pTxtBxs->Append( *pObj, rShapeId );
2626 nTxtId = pTxtBxs->Count();
2628 else
2629 ++nTxtId;
2631 else
2633 const SdrObject* pPrevObj = pFmt->FindRealSdrObject();
2634 nTxtId = pTxtBxs->GetPos( pPrevObj );
2635 if( USHRT_MAX == nTxtId )
2637 sal_uInt32 nPrevShapeId =
2638 GetFlyShapeId(*pFmt, rObj.mnHdFtIndex, rPVec);
2639 pTxtBxs->Append( *pPrevObj, nPrevShapeId );
2640 nTxtId = pTxtBxs->Count();
2642 else
2643 ++nTxtId;
2645 nTxtId *= 0x10000;
2646 nTxtId += nOff;
2648 nBorderThick = WriteTxtFlyFrame(rObj, rShapeId, nTxtId, rPVec);
2652 return nBorderThick;
2655 sal_uInt16 FindPos(const SwFrmFmt &rFmt, unsigned int nHdFtIndex,
2656 DrawObjPointerVector &rPVec)
2658 DrawObjPointerIter aEnd = rPVec.end();
2659 for (DrawObjPointerIter aIter = rPVec.begin(); aIter != aEnd; ++aIter)
2661 const DrawObj *pObj = (*aIter);
2662 OSL_ENSURE(pObj, "Impossible");
2663 if (!pObj)
2664 continue;
2665 if (
2666 nHdFtIndex == pObj->mnHdFtIndex &&
2667 &rFmt == (&pObj->maCntnt.GetFrmFmt())
2670 return static_cast< sal_uInt16 >(aIter - rPVec.begin());
2673 return USHRT_MAX;
2676 sal_Int32 SwEscherEx::WriteTxtFlyFrame(const DrawObj &rObj, sal_uInt32 nShapeId,
2677 sal_uInt32 nTxtBox, DrawObjPointerVector &rPVec)
2679 const SwFrmFmt &rFmt = rObj.maCntnt.GetFrmFmt();
2680 short nDirection = rObj.mnDirection;
2682 sal_Int32 nBorderThick=0;
2683 OpenContainer( ESCHER_SpContainer );
2685 AddShape( ESCHER_ShpInst_TextBox, 0xa00, nShapeId );
2686 EscherPropertyContainer aPropOpt;
2687 aPropOpt.AddOpt(ESCHER_Prop_lTxid, nTxtBox);
2688 if (const SwFrmFmt *pNext = rFmt.GetChain().GetNext())
2690 sal_uInt16 nPos = FindPos(*pNext, rObj.mnHdFtIndex, rPVec);
2691 if (USHRT_MAX != nPos && aFollowShpIds[nPos])
2692 aPropOpt.AddOpt(ESCHER_Prop_hspNext, aFollowShpIds[nPos]);
2694 nBorderThick = WriteFlyFrameAttr( rFmt, mso_sptTextBox, aPropOpt );
2696 MSO_TextFlow nFlow;
2698 switch (nDirection)
2700 default:
2701 OSL_ENSURE(!this, "unknown direction type");
2702 case FRMDIR_HORI_LEFT_TOP:
2703 nFlow=mso_txflHorzN;
2704 break;
2705 case FRMDIR_HORI_RIGHT_TOP:
2706 nFlow=mso_txflHorzN;
2707 break;
2708 case FRMDIR_VERT_TOP_LEFT: //not really possible in word
2709 case FRMDIR_VERT_TOP_RIGHT:
2710 nFlow=mso_txflTtoBA;
2711 break;
2713 aPropOpt.AddOpt( ESCHER_Prop_txflTextFlow, nFlow );
2715 aPropOpt.Commit( GetStream() );
2717 // store anchor attribute
2718 WriteFrmExtraData( rFmt );
2720 AddAtom( 4, ESCHER_ClientTextbox ); GetStream() << nTxtBox;
2722 CloseContainer(); // ESCHER_SpContainer
2723 return nBorderThick;
2726 void SwBasicEscherEx::WriteOLEPicture(EscherPropertyContainer &rPropOpt,
2727 sal_uInt32 nShapeFlags, const Graphic &rGraphic, const SdrObject &rObj,
2728 sal_uInt32 nShapeId, const awt::Rectangle* pVisArea )
2730 //nShapeFlags == 0xA00 + flips and ole active
2731 AddShape(ESCHER_ShpInst_PictureFrame, nShapeFlags, nShapeId);
2733 GraphicObject aGraphicObject(rGraphic);
2734 OString aId = aGraphicObject.GetUniqueID();
2735 if (!aId.isEmpty())
2737 Rectangle aRect = rObj.GetLogicRect();
2738 aRect.SetPos(Point(0,0));
2739 aRect.Right() = DrawModelToEmu(aRect.Right());
2740 aRect.Bottom() = DrawModelToEmu(aRect.Bottom());
2741 sal_uInt32 nBlibId = mxGlobal->GetBlibID( *QueryPictureStream(),
2742 aId, aRect, pVisArea, 0); // SJ: the fourth parameter (VisArea) should be set..
2743 if (nBlibId)
2744 rPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, sal_True);
2747 SetPicId(rObj, nShapeId, rPropOpt);
2748 rPropOpt.AddOpt( ESCHER_Prop_pictureActive, 0x10000 );
2751 void SwEscherEx::WriteOCXControl( const SwFrmFmt& rFmt, sal_uInt32 nShapeId )
2753 if (const SdrObject* pSdrObj = rFmt.FindRealSdrObject())
2755 OpenContainer( ESCHER_SpContainer );
2757 SdrModel *pModel = rWrt.pDoc->GetDrawModel();
2758 OutputDevice *pDevice = Application::GetDefaultDevice();
2759 OSL_ENSURE(pModel && pDevice, "no model or device");
2761 // #i71538# use complete SdrViews
2762 // SdrExchangeView aExchange(pModel, pDevice);
2763 SdrView aExchange(pModel, pDevice);
2765 Graphic aGraphic(aExchange.GetObjGraphic(pModel, pSdrObj));
2767 EscherPropertyContainer aPropOpt;
2768 WriteOLEPicture(aPropOpt, 0xa00 | SHAPEFLAG_OLESHAPE, aGraphic,
2769 *pSdrObj, nShapeId, NULL );
2771 WriteFlyFrameAttr( rFmt, mso_sptPictureFrame , aPropOpt );
2772 aPropOpt.Commit( GetStream() );
2774 // store anchor attribute
2775 WriteFrmExtraData( rFmt );
2777 CloseContainer(); // ESCHER_SpContainer
2781 void SwEscherEx::MakeZOrderArrAndFollowIds(
2782 std::vector<DrawObj>& rSrcArr, std::vector<DrawObj*>&rDstArr)
2784 ::lcl_makeZOrderArray(rWrt, rSrcArr, rDstArr);
2786 //Now set up the follow IDs
2787 aFollowShpIds.clear();
2789 for (size_t n = 0; n < rDstArr.size(); ++n)
2791 const SwFrmFmt &rFmt = rDstArr[n]->maCntnt.GetFrmFmt();
2792 bool bNeedsShapeId = false;
2794 if (RES_FLYFRMFMT == rFmt.Which())
2796 const SwFmtChain &rChain = rFmt.GetChain();
2797 if (rChain.GetPrev() || rChain.GetNext())
2798 bNeedsShapeId = true;
2801 sal_uLong nShapeId = bNeedsShapeId ? GenerateShapeId() : 0;
2803 aFollowShpIds.push_back(nShapeId);
2807 sal_uInt32 SwEscherEx::GetFlyShapeId(const SwFrmFmt& rFmt,
2808 unsigned int nHdFtIndex, DrawObjPointerVector &rpVec)
2810 sal_uInt16 nPos = FindPos(rFmt, nHdFtIndex, rpVec);
2811 sal_uInt32 nShapeId;
2812 if (USHRT_MAX != nPos)
2814 if (0 == (nShapeId = aFollowShpIds[nPos]))
2816 nShapeId = GenerateShapeId();
2817 aFollowShpIds[ nPos ] = nShapeId;
2820 else
2821 nShapeId = GenerateShapeId();
2822 return nShapeId;
2825 sal_uInt32 SwEscherEx::QueryTextID(
2826 const uno::Reference< drawing::XShape>& xXShapeRef, sal_uInt32 nShapeId )
2828 sal_uInt32 nId = 0;
2829 if (SdrObject* pObj = GetSdrObjectFromXShape(xXShapeRef))
2831 pTxtBxs->Append( *pObj, nShapeId );
2832 nId = pTxtBxs->Count();
2833 nId *= 0x10000;
2835 return nId;
2838 SwMSConvertControls::SwMSConvertControls( SfxObjectShell *pDSh,SwPaM *pP ) : oox
2839 ::ole::MSConvertOCXControls( pDSh ? pDSh->GetModel() : NULL ), pPaM( pP ), mnObjectId(0)
2843 sal_uInt32 SwMSConvertControls::GenerateObjectID()
2845 return ++mnObjectId;
2848 // in transitioning away old filter for ole/ocx controls, ReadOCXStream has been made pure virtual in
2849 // filter/source/msocximex.cxx, so.. we need an implementation here
2850 sal_Bool SwMSConvertControls::ReadOCXStream( SotStorageRef& rSrc1,
2851 com::sun::star::uno::Reference< com::sun::star::drawing::XShape > *pShapeRef,
2852 sal_Bool bFloatingCtrl )
2854 uno::Reference< form::XFormComponent > xFComp;
2855 sal_Bool bRes = oox::ole::MSConvertOCXControls::ReadOCXStorage( rSrc1, xFComp );
2856 if ( bRes && xFComp.is() )
2858 com::sun::star::awt::Size aSz; // not used in import
2859 bRes = InsertControl( xFComp, aSz,pShapeRef,bFloatingCtrl);
2861 return bRes;
2864 bool SwMSConvertControls::ExportControl(WW8Export &rWW8Wrt, const SdrObject *pObj)
2866 if (!rWW8Wrt.bWrtWW8)
2867 return false;
2869 SdrUnoObj *pFormObj = PTR_CAST(SdrUnoObj,pObj);
2870 uno::Reference< awt::XControlModel > xControlModel =
2871 pFormObj->GetUnoControlModel();
2873 //Why oh lord do we use so many different units ?
2874 //I think I painted myself into a little bit of a
2875 //corner by trying to use the uno interface for
2876 //controls export
2877 Rectangle aRect = pFormObj->GetLogicRect();
2878 aRect.SetPos(Point(0,0));
2879 awt::Size aSize;
2880 aSize.Width = TWIPS_TO_MM(aRect.Right());
2881 aSize.Height = TWIPS_TO_MM(aRect.Bottom());
2883 //Open the ObjectPool
2884 SvStorageRef xObjPool = rWW8Wrt.GetWriter().GetStorage().OpenSotStorage(
2885 OUString(SL::aObjectPool), STREAM_READWRITE |
2886 STREAM_SHARE_DENYALL);
2888 //Create a destination storage for the microsoft control
2889 OUStringBuffer sStorageName;
2890 sal_uInt32 nObjId = GenerateObjectID();
2891 sStorageName.append('_').append( static_cast<sal_Int64>( nObjId ));
2892 SvStorageRef xOleStg = xObjPool->OpenSotStorage(sStorageName.makeStringAndClear(),
2893 STREAM_READWRITE|STREAM_SHARE_DENYALL);
2895 if (!xOleStg.Is())
2896 return false;
2899 OUString sUName;
2900 if (!WriteOCXStream( mxModel, xOleStg,xControlModel,aSize,sUName))
2901 return false;
2903 String sName = sUName;
2905 sal_uInt8 aSpecOLE[] =
2907 0x03, 0x6a, 0xFF, 0xFF, 0xFF, 0xFF, // sprmCPicLocation
2908 0x0a, 0x08, 1, // sprmCFOLE2
2909 0x55, 0x08, 1, // sprmCFSpec
2910 0x56, 0x08, 1 // sprmCFObj
2912 //Set the obj id into the sprmCPicLocation
2913 sal_uInt8 *pData = aSpecOLE+2;
2914 Set_UInt32(pData,nObjId );
2916 String sFld(FieldString(ww::eCONTROL));
2917 sFld.AppendAscii("Forms.");
2918 sFld += sName;
2919 sFld.AppendAscii(".1 \\s ");
2921 rWW8Wrt.OutputField(0, ww::eCONTROL, sFld,
2922 WRITEFIELD_START|WRITEFIELD_CMD_START|WRITEFIELD_CMD_END);
2924 rWW8Wrt.pChpPlc->AppendFkpEntry(rWW8Wrt.Strm().Tell(),sizeof(aSpecOLE),
2925 aSpecOLE);
2926 rWW8Wrt.WriteChar( 0x1 );
2927 rWW8Wrt.OutputField(0, ww::eCONTROL, aEmptyStr, WRITEFIELD_END | WRITEFIELD_CLOSE);
2928 return true;
2931 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */