build fix
[LibreOffice.git] / sw / source / filter / ww8 / wrtw8esh.cxx
blob8790bea99a0518e79a21ab9b244ddb282bb15388
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 <o3tl/any.hxx>
25 #include <vcl/cvtgrf.hxx>
26 #include <vcl/virdev.hxx>
27 #include <com/sun/star/drawing/XShape.hpp>
28 #include <vcl/svapp.hxx>
29 #include <sot/storage.hxx>
30 #include <vcl/graphicfilter.hxx>
31 #include <svl/itemiter.hxx>
32 #include <svl/whiter.hxx>
33 #include <svx/svdobj.hxx>
34 #include <svx/svdotext.hxx>
35 #include <svx/svdmodel.hxx>
36 #include <svx/svdpage.hxx>
37 #include <editeng/outlobj.hxx>
38 #include <editeng/editobj.hxx>
39 #include <svx/unoshape.hxx>
40 #include <editeng/brushitem.hxx>
41 #include <editeng/boxitem.hxx>
42 #include <editeng/lrspitem.hxx>
43 #include <editeng/ulspitem.hxx>
44 #include <editeng/fontitem.hxx>
45 #include <editeng/frmdiritem.hxx>
46 #include <svx/svdoole2.hxx>
47 #include <editeng/editeng.hxx>
48 #include <editeng/flditem.hxx>
49 #include <editeng/shaditem.hxx>
50 #include <unotools/ucbstreamhelper.hxx>
51 #include <svx/fmglob.hxx>
52 #include <svx/svdouno.hxx>
53 #include <svx/unoapi.hxx>
54 #include <svx/svdview.hxx>
55 #include <fmtcnct.hxx>
56 #include <fmtanchr.hxx>
57 #include <fmtsrnd.hxx>
58 #include <fmtornt.hxx>
59 #include <fmtfsize.hxx>
60 #include <fmtfollowtextflow.hxx>
61 #include <dcontact.hxx>
62 #include <frmfmt.hxx>
63 #include <frmatr.hxx>
64 #include <fmtcntnt.hxx>
65 #include <ndindex.hxx>
66 #include <doc.hxx>
67 #include <drawdoc.hxx>
68 #include <IDocumentSettingAccess.hxx>
69 #include <IDocumentDrawModelAccess.hxx>
70 #include <docary.hxx>
71 #include <pam.hxx>
72 #include <swrect.hxx>
73 #include <ndgrf.hxx>
74 #include <grfatr.hxx>
75 #include <ndole.hxx>
76 #include <unodraw.hxx>
77 #include <pagedesc.hxx>
78 #include <ww8par.hxx>
79 #include <breakit.hxx>
80 #include <com/sun/star/i18n/ScriptType.hpp>
81 #include "ww8attributeoutput.hxx"
82 #include "writerhelper.hxx"
83 #include "writerwordglue.hxx"
84 #include "wrtww8.hxx"
85 #include "escher.hxx"
86 #include <ndtxt.hxx>
87 #include "WW8FFData.hxx"
88 #include <com/sun/star/beans/XPropertyContainer.hpp>
89 #include <com/sun/star/beans/XPropertySet.hpp>
90 #include <com/sun/star/beans/PropertyAttribute.hpp>
91 #include <com/sun/star/form/XFormComponent.hpp>
92 #include "docsh.hxx"
93 #include "IDocumentStylePoolAccess.hxx"
94 #include <oox/ole/olehelper.hxx>
95 #include <fstream>
96 #include <unotools/streamwrap.hxx>
97 #include <fmtinfmt.hxx>
98 #include <fmturl.hxx>
99 #include "sfx2/sfxsids.hrc"
100 #include <svl/urihelper.hxx>
101 #include <unotools/saveopt.hxx>
102 #include <o3tl/enumrange.hxx>
103 #include <o3tl/enumarray.hxx>
105 #include <algorithm>
107 using ::editeng::SvxBorderLine;
108 using namespace com::sun::star;
109 using namespace sw::util;
110 using namespace sw::types;
111 using namespace nsFieldFlags;
112 using ::com::sun::star::beans::XPropertySet;
113 using ::com::sun::star::drawing::XShape;
115 bool SwBasicEscherEx::IsRelUrl()
117 SvtSaveOptions aSaveOpt;
118 bool bRelUrl = false;
119 SfxMedium * pMedium = rWrt.GetWriter().GetMedia();
120 if ( pMedium )
121 bRelUrl = pMedium->IsRemote() ? aSaveOpt.IsSaveRelINet() : aSaveOpt.IsSaveRelFSys();
122 return bRelUrl;
125 OUString SwBasicEscherEx::GetBasePath()
127 OUString sDocUrl;
128 SfxMedium * pMedium = rWrt.GetWriter().GetMedia();
129 if (pMedium)
131 const SfxItemSet* pPItemSet = pMedium->GetItemSet();
132 if( pPItemSet )
134 const SfxStringItem* pPItem = dynamic_cast< const SfxStringItem* >( pPItemSet->GetItem( SID_FILE_NAME ) );
135 if ( pPItem )
136 sDocUrl = pPItem->GetValue();
140 return sDocUrl.copy(0, sDocUrl.lastIndexOf('/') + 1);
143 OUString SwBasicEscherEx::BuildFileName(sal_uInt16& rnLevel, bool& rbRel, const OUString& rUrl)
145 OUString aDosName( INetURLObject( rUrl ).getFSysPath( INetURLObject::FSYS_DOS ) );
146 rnLevel = 0;
147 rbRel = IsRelUrl();
149 if (rbRel)
151 // try to convert to relative file name
152 OUString aTmpName( aDosName );
153 aDosName = INetURLObject::GetRelURL( GetBasePath(), rUrl,
154 INetURLObject::EncodeMechanism::WasEncoded, INetURLObject::DecodeMechanism::WithCharset );
156 if (aDosName.startsWith(INET_FILE_SCHEME))
158 // not converted to rel -> back to old, return absolute flag
159 aDosName = aTmpName;
160 rbRel = false;
162 else if (aDosName.startsWith("./"))
164 aDosName = aDosName.copy(2);
166 else
168 while (aDosName.startsWith("../"))
170 ++rnLevel;
171 aDosName = aDosName.copy(3);
175 return aDosName;
178 void SwBasicEscherEx::WriteHyperlinkWithinFly( SvMemoryStream& rStrm, const SwFormatURL* pINetFormatArg)
180 if ( !pINetFormatArg ) return;
182 sal_uInt8 aGuidStdLink[ 16 ] ={
183 0xD0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE, 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B };
184 sal_uInt8 aGuidUrlMoniker[ 16 ] = {
185 0xE0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE, 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B };
187 sal_uInt8 aGuidFileMoniker[ 16 ] = {
188 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };
189 sal_uInt8 aGuidFileTail[] = {
190 0xFF, 0xFF, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00,
191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
194 //const sal_uInt18 WW8_ID_HLINK = 0x01B8;
195 const sal_uInt32 WW8_HLINK_BODY = 0x00000001; /// Contains file link or URL.
196 const sal_uInt32 WW8_HLINK_ABS = 0x00000002; /// Absolute path.
197 //const sal_uInt32 WW8_HLINK_DESCR = 0x00000014; /// Description.
198 const sal_uInt32 WW8_HLINK_MARK = 0x00000008; /// Text mark.
199 const sal_uInt32 WW8_HLINK_FRAME = 0x00000080; /// Target frame.
200 //const sal_uInt32 WW8_HLINK_UNC = 0x00000100; /// UNC path.
201 SvMemoryStream tmpStrm;
202 OUString tmpTextMark;
204 OUString rUrl = pINetFormatArg->GetURL();
205 OUString rTarFrame = pINetFormatArg->GetTargetFrameName();
206 sal_uInt32 nFlags = 0;
208 INetURLObject aUrlObj( rUrl );
209 const INetProtocol eProtocol = aUrlObj.GetProtocol();
211 //Target Frame
212 if (!rTarFrame.isEmpty())
214 SwWW8Writer::WriteLong(tmpStrm, rTarFrame.getLength()+1);
215 SwWW8Writer::WriteString16(tmpStrm, rTarFrame, false);
217 tmpStrm.WriteUInt16( 0 );
219 nFlags |= WW8_HLINK_FRAME;
222 // file link or URL
223 if (eProtocol == INetProtocol::File || (eProtocol == INetProtocol::NotValid && rUrl[0] != '#'))
225 sal_uInt16 nLevel;
226 bool bRel;
227 OUString aFileName( BuildFileName( nLevel, bRel, rUrl ));
229 if( !bRel )
230 nFlags |= WW8_HLINK_ABS;
232 nFlags |= WW8_HLINK_BODY;
234 tmpStrm.WriteBytes(aGuidFileMoniker, sizeof(aGuidFileMoniker));
235 tmpStrm.WriteUInt16( nLevel );
236 SwWW8Writer::WriteLong(tmpStrm, aFileName.getLength()+1);
237 SwWW8Writer::WriteString8( tmpStrm, aFileName, true, RTL_TEXTENCODING_MS_1252 );
238 tmpStrm.WriteBytes(aGuidFileTail, sizeof(aGuidFileTail));
240 //For UNICODE
241 SwWW8Writer::WriteLong(tmpStrm, 2*aFileName.getLength()+6);
242 SwWW8Writer::WriteLong(tmpStrm, 2*aFileName.getLength());
243 tmpStrm.WriteUInt16( 0x0003 );
244 SwWW8Writer::WriteString16(tmpStrm, aFileName, false);
246 else if( eProtocol != INetProtocol::NotValid )
248 tmpStrm.WriteBytes(aGuidUrlMoniker, sizeof(aGuidUrlMoniker));
249 SwWW8Writer::WriteLong(tmpStrm, 2*(rUrl.getLength()+1));
251 SwWW8Writer::WriteString16(tmpStrm, rUrl, true);
252 nFlags |= WW8_HLINK_BODY | WW8_HLINK_ABS;
254 else if (rUrl[0] == '#' )
256 OUString aTextMark(rUrl.copy( 1 ));
257 aTextMark = aTextMark.replaceFirst(".", "!");
258 tmpTextMark = aTextMark;
261 if (tmpTextMark.isEmpty() && aUrlObj.HasMark())
263 tmpTextMark = aUrlObj.GetMark();
266 if (!tmpTextMark.isEmpty())
268 SwWW8Writer::WriteLong(tmpStrm, tmpTextMark.getLength()+1);
269 SwWW8Writer::WriteString16(tmpStrm, tmpTextMark, true);
271 nFlags |= WW8_HLINK_MARK;
274 rStrm.WriteBytes(aGuidStdLink, 16);
275 rStrm .WriteUInt32( 2 )
276 .WriteUInt32( nFlags );
277 tmpStrm.Seek( STREAM_SEEK_TO_BEGIN );
278 sal_uInt32 const nLen = tmpStrm.remainingSize();
279 if(nLen >0)
281 std::unique_ptr<sal_uInt8[]> pBuffer( new sal_uInt8[ nLen ] );
282 tmpStrm.ReadBytes(pBuffer.get(), nLen);
283 rStrm.WriteBytes(pBuffer.get(), nLen);
286 void SwBasicEscherEx::PreWriteHyperlinkWithinFly(const SwFrameFormat& rFormat,EscherPropertyContainer& rPropOpt)
288 const SfxPoolItem* pItem;
289 const SwAttrSet& rAttrSet = rFormat.GetAttrSet();
290 if (SfxItemState::SET == rAttrSet.GetItemState(RES_URL, true, &pItem))
292 const SwFormatURL *pINetFormat = dynamic_cast<const SwFormatURL*>(pItem);
293 if (pINetFormat && !pINetFormat->GetURL().isEmpty())
295 SvMemoryStream *rStrm = new SvMemoryStream ;
296 WriteHyperlinkWithinFly( *rStrm, pINetFormat );
297 sal_uInt8 const * pBuf = static_cast<sal_uInt8 const *>(rStrm->GetData());
298 sal_uInt32 nSize = rStrm->Seek( STREAM_SEEK_TO_END );
299 rPropOpt.AddOpt( ESCHER_Prop_pihlShape, true, nSize, const_cast<sal_uInt8 *>(pBuf), nSize );
300 sal_uInt32 nValue;
301 OUString aNamestr = pINetFormat->GetName();
302 if (!aNamestr.isEmpty())
304 rPropOpt.AddOpt(ESCHER_Prop_wzName, aNamestr );
306 if(rPropOpt.GetOpt( ESCHER_Prop_fPrint, nValue))
308 nValue|=0x03080008;
309 rPropOpt.AddOpt(ESCHER_Prop_fPrint, nValue );
311 else
312 rPropOpt.AddOpt(ESCHER_Prop_fPrint, 0x03080008 );
317 namespace
319 /// Get the Z ordering number for a DrawObj in a WW8Export.
320 /// @param rWrt The containing WW8Export.
321 /// @param pObj pointer to the drawing object.
322 /// @returns The ordering number.
323 sal_uLong lcl_getSdrOrderNumber(const WW8Export& rWrt, DrawObj *pObj)
325 return rWrt.GetSdrOrdNum(pObj->maContent.GetFrameFormat());
328 /// A function object to act as a predicate comparing the ordering numbers
329 /// of two drawing obejcts in a WW8Export.
330 class CompareDrawObjs
332 private:
333 const WW8Export& wrt;
335 public:
336 explicit CompareDrawObjs(const WW8Export& rWrt) : wrt(rWrt) {};
337 bool operator()(DrawObj *a, DrawObj *b) const
339 sal_uLong aSort = lcl_getSdrOrderNumber(wrt, a);
340 sal_uLong bSort = lcl_getSdrOrderNumber(wrt, b);
341 return aSort < bSort;
345 /// Make a z-order sorted copy of a collection of DrawObj objects.
346 /// @param rWrt The containing WW8Export.
347 /// @param rSrcArr The source array.
348 /// @param rDstArr The destination array.
349 void lcl_makeZOrderArray(const WW8Export& rWrt,
350 std::vector<DrawObj> &rSrcArr,
351 std::vector<DrawObj*> &rDstArr)
353 rDstArr.clear();
354 rDstArr.reserve(rSrcArr.size());
355 for(DrawObj & i : rSrcArr)
357 rDstArr.push_back( &i );
359 std::sort(rDstArr.begin(), rDstArr.end(), CompareDrawObjs(rWrt));
364 // get a part fix for this type of element
365 bool WW8Export::MiserableFormFieldExportHack(const SwFrameFormat& rFrameFormat)
367 const SdrObject *pObject = rFrameFormat.FindRealSdrObject();
368 if (!pObject || pObject->GetObjInventor() != SdrInventor::FmForm)
369 return false;
371 const SdrUnoObj *pFormObj = dynamic_cast< const SdrUnoObj* >(pObject);
372 if (!pFormObj)
373 return false;
375 uno::Reference< awt::XControlModel > xControlModel =
376 pFormObj->GetUnoControlModel();
377 uno::Reference< lang::XServiceInfo > xInfo(xControlModel,
378 uno::UNO_QUERY);
379 uno::Reference<beans::XPropertySet> xPropSet(xControlModel, uno::UNO_QUERY);
380 if (!xInfo.is())
381 return false;
383 if (xInfo->supportsService("com.sun.star.form.component.ComboBox"))
385 DoComboBox(xPropSet);
386 return true;
389 return false;
392 void WW8Export::DoComboBox(uno::Reference<beans::XPropertySet> const & xPropSet)
394 OUString sSelected;
395 uno::Sequence<OUString> aListItems;
396 xPropSet->getPropertyValue("StringItemList") >>= aListItems;
397 sal_Int32 nNoStrings = aListItems.getLength();
398 if (nNoStrings)
400 uno::Any aTmp = xPropSet->getPropertyValue("DefaultText");
401 auto pStr = o3tl::tryAccess<OUString>(aTmp);
402 if (pStr)
403 sSelected = *pStr;
406 OUString sName;
408 uno::Any aTmp = xPropSet->getPropertyValue("Name");
409 auto pStr = o3tl::tryAccess<OUString>(aTmp);
410 if (pStr)
411 sName = *pStr;
414 OUString sHelp;
416 // property "Help" does not exist and due to the no-existence an exception is thrown.
419 uno::Any aTmp = xPropSet->getPropertyValue("HelpText");
420 auto pStr = o3tl::tryAccess<OUString>(aTmp);
421 if (pStr)
422 sHelp = *pStr;
424 catch( const uno::Exception& )
428 OUString sToolTip;
430 uno::Any aTmp = xPropSet->getPropertyValue("Name");
431 auto pStr = o3tl::tryAccess<OUString>(aTmp);
432 if (pStr)
433 sToolTip = *pStr;
436 DoComboBox(sName, sHelp, sToolTip, sSelected, aListItems);
439 void WW8Export::DoComboBox(const OUString &rName,
440 const OUString &rHelp,
441 const OUString &rToolTip,
442 const OUString &rSelected,
443 uno::Sequence<OUString> &rListItems)
445 OutputField(nullptr, ww::eFORMDROPDOWN, FieldString(ww::eFORMDROPDOWN),
446 WRITEFIELD_START | WRITEFIELD_CMD_START);
447 // write the refence to the "picture" structure
448 sal_uLong nDataStt = pDataStrm->Tell();
449 m_pChpPlc->AppendFkpEntry( Strm().Tell() );
451 WriteChar( 0x01 );
453 static sal_uInt8 aArr1[] =
455 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
456 0x06, 0x08, 0x01, // sprmCFData
457 0x55, 0x08, 0x01, // sprmCFSpec
458 0x02, 0x08, 0x01 // sprmCFFieldVanish
460 sal_uInt8* pDataAdr = aArr1 + 2;
461 Set_UInt32( pDataAdr, nDataStt );
463 m_pChpPlc->AppendFkpEntry(Strm().Tell(), sizeof(aArr1), aArr1);
465 OutputField(nullptr, ww::eFORMDROPDOWN, FieldString(ww::eFORMDROPDOWN),
466 WRITEFIELD_CLOSE);
468 ::sw::WW8FFData aFFData;
470 aFFData.setType(2);
471 aFFData.setName(rName);
472 aFFData.setHelp(rHelp);
473 aFFData.setStatus(rToolTip);
475 sal_uInt32 nListItems = rListItems.getLength();
477 for (sal_uInt32 i = 0; i < nListItems; i++)
479 if (i < 0x20 && rSelected == rListItems[i])
480 aFFData.setResult(::sal::static_int_cast<sal_uInt8>(i));
481 aFFData.addListboxEntry(rListItems[i]);
484 aFFData.Write(pDataStrm);
487 void WW8Export::DoFormText(const SwInputField * pField)
489 OutputField(nullptr, ww::eFORMTEXT, FieldString(ww::eFORMTEXT),
490 WRITEFIELD_START | WRITEFIELD_CMD_START);
491 // write the refence to the "picture" structure
492 sal_uLong nDataStt = pDataStrm->Tell();
493 m_pChpPlc->AppendFkpEntry( Strm().Tell() );
495 WriteChar( 0x01 );
496 static sal_uInt8 aArr1[] = {
497 0x02, 0x08, 0x81, // sprmCFFieldVanish
498 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
500 0x06, 0x08, 0x01, // sprmCFData
501 0x55, 0x08, 0x01 // sprmCFSpec
503 sal_uInt8* pDataAdr = aArr1 + 5;
504 Set_UInt32( pDataAdr, nDataStt );
506 m_pChpPlc->AppendFkpEntry(Strm().Tell(),
507 sizeof( aArr1 ), aArr1 );
509 ::sw::WW8FFData aFFData;
511 aFFData.setType(0);
512 aFFData.setName(pField->GetPar2());
513 aFFData.setHelp(pField->GetHelp());
514 aFFData.setStatus(pField->GetToolTip());
515 aFFData.Write(pDataStrm);
517 OutputField(nullptr, ww::eFORMTEXT, OUString(), WRITEFIELD_CMD_END);
519 const OUString fieldStr( pField->ExpandField(true) );
520 SwWW8Writer::WriteString16(Strm(), fieldStr, false);
522 static sal_uInt8 aArr2[] = {
523 0x55, 0x08, 0x01, // sprmCFSpec
524 0x75, 0x08, 0x01 // ???
527 pDataAdr = aArr2 + 2;
528 Set_UInt32( pDataAdr, nDataStt );
529 m_pChpPlc->AppendFkpEntry(Strm().Tell(),
530 sizeof( aArr2 ), aArr2 );
532 OutputField(nullptr, ww::eFORMTEXT, OUString(), WRITEFIELD_CLOSE);
535 PlcDrawObj::~PlcDrawObj()
539 //Its irritating to have to change the RTL frames position into LTR ones
540 //so that word will have to place them in the right place. Doubly so that
541 //the SO drawings and writer frames have different ideas themselves as to
542 //how to be positioned when in RTL mode!
543 bool RTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth,
544 sal_Int16 eHoriOri, sal_Int16 eHoriRel, SwTwips nPageLeft,
545 SwTwips nPageRight, SwTwips nPageSize)
547 bool bRet = false;
548 if (eHoriOri == text::HoriOrientation::NONE)
550 if (eHoriRel == text::RelOrientation::PAGE_FRAME)
552 rLeft = nPageSize - rLeft;
553 bRet = true;
555 else if (
556 (eHoriRel == text::RelOrientation::PAGE_PRINT_AREA) ||
557 (eHoriRel == text::RelOrientation::FRAME) ||
558 (eHoriRel == text::RelOrientation::PRINT_AREA)
561 rLeft = nPageSize - nPageLeft - nPageRight - rLeft;
562 bRet = true;
565 if (bRet)
566 rLeft -= nWidth;
567 return bRet;
570 bool RTLDrawingsHack(long &rLeft, long /*nWidth*/,
571 sal_Int16 eHoriOri, sal_Int16 eHoriRel, SwTwips nPageLeft,
572 SwTwips nPageRight, SwTwips nPageSize)
574 bool bRet = false;
575 if (eHoriOri == text::HoriOrientation::NONE)
577 if (eHoriRel == text::RelOrientation::PAGE_FRAME)
579 rLeft = nPageSize + rLeft;
580 bRet = true;
582 else if (
583 (eHoriRel == text::RelOrientation::PAGE_PRINT_AREA) ||
584 (eHoriRel == text::RelOrientation::FRAME) ||
585 (eHoriRel == text::RelOrientation::PRINT_AREA)
588 rLeft = nPageSize - nPageLeft - nPageRight + rLeft;
589 bRet = true;
592 return bRet;
595 void WW8Export::MiserableRTLFrameFormatHack(SwTwips &rLeft, SwTwips &rRight,
596 const ww8::Frame &rFrameFormat)
598 //Require nasty bidi swap
599 if (FRMDIR_HORI_RIGHT_TOP != m_pDoc->GetTextDirection(rFrameFormat.GetPosition()))
600 return;
602 SwTwips nWidth = rRight - rLeft;
603 SwTwips nPageLeft, nPageRight;
604 SwTwips nPageSize = CurrentPageWidth(nPageLeft, nPageRight);
606 const SwFormatHoriOrient& rHOr = rFrameFormat.GetFrameFormat().GetHoriOrient();
608 bool bRet = false;
609 ww8::Frame::WriterSource eSource = rFrameFormat.GetWriterType();
610 if (eSource == ww8::Frame::eDrawing || eSource == ww8::Frame::eFormControl)
612 if (RTLDrawingsHack(rLeft, nWidth, rHOr.GetHoriOrient(),
613 rHOr.GetRelationOrient(), nPageLeft, nPageRight, nPageSize))
615 bRet = true;
618 else
620 if (RTLGraphicsHack(rLeft, nWidth, rHOr.GetHoriOrient(),
621 rHOr.GetRelationOrient(), nPageLeft, nPageRight, nPageSize))
623 bRet = true;
626 if (bRet)
627 rRight = rLeft + nWidth;
630 void PlcDrawObj::WritePlc( WW8Export& rWrt ) const
632 if (8 > rWrt.pFib->m_nVersion) // Cannot export drawobject in vers 7-
633 return;
635 sal_uInt32 nFcStart = rWrt.pTableStrm->Tell();
637 if (!maDrawObjs.empty())
639 // write CPs
640 WW8Fib& rFib = *rWrt.pFib;
641 WW8_CP nCpOffs = GetCpOffset(rFib);
643 cDrawObjIter aEnd = maDrawObjs.end();
644 cDrawObjIter aIter;
646 for (aIter = maDrawObjs.begin(); aIter < aEnd; ++aIter)
647 SwWW8Writer::WriteLong(*rWrt.pTableStrm, aIter->mnCp - nCpOffs);
649 SwWW8Writer::WriteLong(*rWrt.pTableStrm, rFib.m_ccpText + rFib.m_ccpFootnote +
650 rFib.m_ccpHdr + rFib.m_ccpEdn + rFib.m_ccpTxbx + rFib.m_ccpHdrTxbx + 1);
652 for (aIter = maDrawObjs.begin(); aIter < aEnd; ++aIter)
654 // write the fspa-struct
655 const ww8::Frame &rFrameFormat = aIter->maContent;
656 const SwFrameFormat &rFormat = rFrameFormat.GetFrameFormat();
657 const SdrObject* pObj = rFormat.FindRealSdrObject();
659 Rectangle aRect;
660 SwFormatVertOrient rVOr = rFormat.GetVertOrient();
661 SwFormatHoriOrient rHOr = rFormat.GetHoriOrient();
662 // #i30669# - convert the positioning attributes.
663 // Most positions are converted, if layout information exists.
664 const bool bPosConverted =
665 WinwordAnchoring::ConvertPosition( rHOr, rVOr, rFormat );
667 Point aObjPos;
668 if (RES_FLYFRMFMT == rFormat.Which())
670 SwRect aLayRect(rFormat.FindLayoutRect(false, &aObjPos));
671 // the Object is not visible - so get the values from
672 // the format. The Position may not be correct.
673 if( aLayRect.IsEmpty() )
674 aRect.SetSize( rFormat.GetFrameSize().GetSize() );
675 else
677 // #i56090# Do not only consider the first client
678 // Note that we actually would have to find the maximum size of the
679 // frame format clients. However, this already should work in most cases.
680 const SwRect aSizeRect(rFormat.FindLayoutRect());
681 if ( aSizeRect.Width() > aLayRect.Width() )
682 aLayRect.Width( aSizeRect.Width() );
684 aRect = aLayRect.SVRect();
687 else
689 OSL_ENSURE(pObj, "wo ist das SDR-Object?");
690 if (pObj)
692 aRect = pObj->GetLogicRect();
696 // #i30669# - use converted position, if conversion is performed.
697 // Unify position determination of Writer fly frames
698 // and drawing objects.
699 if ( bPosConverted )
701 aRect.SetPos( Point( rHOr.GetPos(), rVOr.GetPos() ) );
703 else
705 aRect -= aIter->maParentPos;
706 aObjPos = aRect.TopLeft();
707 if (text::VertOrientation::NONE == rVOr.GetVertOrient())
709 // #i22673#
710 sal_Int16 eOri = rVOr.GetRelationOrient();
711 if (eOri == text::RelOrientation::CHAR || eOri == text::RelOrientation::TEXT_LINE)
712 aObjPos.Y() = -rVOr.GetPos();
713 else
714 aObjPos.Y() = rVOr.GetPos();
716 if (text::HoriOrientation::NONE == rHOr.GetHoriOrient())
717 aObjPos.X() = rHOr.GetPos();
718 aRect.SetPos( aObjPos );
721 sal_Int32 nThick = aIter->mnThick;
723 //If we are being exported as an inline hack, set
724 //corner to 0 and forget about border thickness for positioning
725 if (rFrameFormat.IsInline())
727 aRect.SetPos(Point(0,0));
728 nThick = 0;
731 // spid
732 SwWW8Writer::WriteLong(*rWrt.pTableStrm, aIter->mnShapeId);
734 SwTwips nLeft = aRect.Left() + nThick;
735 SwTwips nRight = aRect.Right() - nThick;
736 SwTwips nTop = aRect.Top() + nThick;
737 SwTwips nBottom = aRect.Bottom() - nThick;
739 // tdf#93675, 0 below line/paragraph and/or top line/paragraph with
740 // wrap top+bottom or other wraps is affecting the line directly
741 // above the anchor line, which seems odd, but a tiny adjustment
742 // here to bring the top down convinces msoffice to wrap like us
743 if (nTop == 0 && !rFrameFormat.IsInline() &&
744 rVOr.GetVertOrient() == text::VertOrientation::NONE &&
745 rVOr.GetRelationOrient() == text::RelOrientation::FRAME)
747 nTop = 8;
750 //Nasty swap for bidi if necessary
751 rWrt.MiserableRTLFrameFormatHack(nLeft, nRight, rFrameFormat);
753 //xaLeft/yaTop/xaRight/yaBottom - rel. to anchor
754 //(most of) the border is outside the graphic is word, so
755 //change dimensions to fit
756 SwWW8Writer::WriteLong(*rWrt.pTableStrm, nLeft);
757 SwWW8Writer::WriteLong(*rWrt.pTableStrm, nTop);
758 SwWW8Writer::WriteLong(*rWrt.pTableStrm, nRight);
759 SwWW8Writer::WriteLong(*rWrt.pTableStrm, nBottom);
761 //fHdr/bx/by/wr/wrk/fRcaSimple/fBelowText/fAnchorLock
762 sal_uInt16 nFlags=0;
763 //If nFlags isn't 0x14 its overridden by the escher properties
764 if (FLY_AT_PAGE == rFormat.GetAnchor().GetAnchorId())
765 nFlags = 0x0000;
766 else
767 nFlags = 0x0014; // x-rel to text, y-rel to text
769 const SwFormatSurround& rSurr = rFormat.GetSurround();
770 sal_uInt16 nContour = rSurr.IsContour() ? 0x0080 : 0x0040;
771 SwSurround eSurround = rSurr.GetSurround();
774 #i3958#
775 The inline elements being export as anchored to character inside
776 the shape field hack are required to be wrap through so as to flow
777 over the following dummy 0x01 graphic
779 if (rFrameFormat.IsInline())
780 eSurround = SURROUND_THROUGHT;
782 switch (eSurround)
784 case SURROUND_NONE:
785 nFlags |= 0x0020;
786 break;
787 case SURROUND_THROUGHT:
788 nFlags |= 0x0060;
789 break;
790 case SURROUND_PARALLEL:
791 nFlags |= 0x0000 | nContour;
792 break;
793 case SURROUND_IDEAL:
794 nFlags |= 0x0600 | nContour;
795 break;
796 case SURROUND_LEFT:
797 nFlags |= 0x0200 | nContour;
798 break;
799 case SURROUND_RIGHT:
800 nFlags |= 0x0400 | nContour;
801 break;
802 default:
803 OSL_ENSURE(false, "Unsupported surround type for export");
804 break;
806 if (pObj && (pObj->GetLayer() == rWrt.m_pDoc->getIDocumentDrawModelAccess().GetHellId() ||
807 pObj->GetLayer() == rWrt.m_pDoc->getIDocumentDrawModelAccess().GetInvisibleHellId()))
809 nFlags |= 0x4000;
813 #i3958# Required to make this inline stuff work in WordXP, not
814 needed for 2003 interestingly
816 if (rFrameFormat.IsInline())
817 nFlags |= 0x8000;
819 SwWW8Writer::WriteShort(*rWrt.pTableStrm, nFlags);
821 // cTxbx
822 SwWW8Writer::WriteLong(*rWrt.pTableStrm, 0);
825 RegisterWithFib(rFib, nFcStart, rWrt.pTableStrm->Tell() - nFcStart);
829 void MainTextPlcDrawObj::RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
830 sal_uInt32 nLen) const
832 rFib.m_fcPlcfspaMom = nStart;
833 rFib.m_lcbPlcfspaMom = nLen;
836 WW8_CP MainTextPlcDrawObj::GetCpOffset(const WW8Fib &) const
838 return 0;
841 void HdFtPlcDrawObj::RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
842 sal_uInt32 nLen) const
844 rFib.m_fcPlcfspaHdr = nStart;
845 rFib.m_lcbPlcfspaHdr = nLen;
848 WW8_CP HdFtPlcDrawObj::GetCpOffset(const WW8Fib &rFib) const
850 return rFib.m_ccpText + rFib.m_ccpFootnote;
853 DrawObj& DrawObj::operator=(const DrawObj& rOther)
855 mnCp = rOther.mnCp;
856 mnShapeId = rOther.mnShapeId;
857 maContent = rOther.maContent;
858 maParentPos = rOther.maParentPos;
859 mnThick = rOther.mnThick;
860 mnDirection = rOther.mnDirection;
861 mnHdFtIndex = rOther.mnHdFtIndex;
862 return *this;
865 bool PlcDrawObj::Append( WW8Export& rWrt, WW8_CP nCp, const ww8::Frame& rFormat,
866 const Point& rNdTopLeft )
868 bool bRet = false;
869 const SwFrameFormat &rFrameFormat = rFormat.GetFrameFormat();
870 if (TXT_HDFT == rWrt.m_nTextTyp || TXT_MAINTEXT == rWrt.m_nTextTyp)
872 if (RES_FLYFRMFMT == rFrameFormat.Which())
874 // check for textflyframe and if it is the first in a Chain
875 if (rFrameFormat.GetContent().GetContentIdx())
876 bRet = true;
878 else
879 bRet = true;
882 if (bRet)
884 DrawObj aObj(rFormat, nCp, rNdTopLeft, rWrt.TrueFrameDirection(rFrameFormat),
885 rWrt.GetHdFtIndex());
886 maDrawObjs.push_back(aObj);
888 return bRet;
891 void DrawObj::SetShapeDetails(sal_uInt32 nId, sal_Int32 nThick)
893 mnShapeId = nId;
894 mnThick = nThick;
897 bool WW8_WrPlcTextBoxes::WriteText( WW8Export& rWrt )
899 rWrt.m_bInWriteEscher = true;
900 WW8_CP& rccp=TXT_TXTBOX == nTyp ? rWrt.pFib->m_ccpTxbx : rWrt.pFib->m_ccpHdrTxbx;
902 bool bRet = WriteGenericText( rWrt, nTyp, rccp );
904 WW8_CP nCP = rWrt.Fc2Cp( rWrt.Strm().Tell() );
905 WW8Fib& rFib = *rWrt.pFib;
906 WW8_CP nMyOffset = rFib.m_ccpText + rFib.m_ccpFootnote + rFib.m_ccpHdr + rFib.m_ccpAtn
907 + rFib.m_ccpEdn;
908 if( TXT_TXTBOX == nTyp )
909 rWrt.m_pFieldTextBxs->Finish( nCP, nMyOffset );
910 else
911 rWrt.m_pFieldHFTextBxs->Finish( nCP, nMyOffset + rFib.m_ccpTxbx );
912 rWrt.m_bInWriteEscher = false;
913 return bRet;
916 void WW8_WrPlcTextBoxes::Append( const SdrObject& rObj, sal_uInt32 nShapeId )
918 aContent.push_back( &rObj );
919 aShapeIds.push_back( nShapeId );
920 //save NULL, if we have an actual SdrObject
921 aSpareFormats.push_back(nullptr);
924 void WW8_WrPlcTextBoxes::Append( const SwFrameFormat* pFormat, sal_uInt32 nShapeId )
926 //no sdr object, we insert a NULL in the aContent and save the real fmt in aSpareFormats.
927 aContent.push_back( nullptr );
928 aShapeIds.push_back( nShapeId );
929 aSpareFormats.push_back(pFormat);
932 const std::vector<sal_uInt32>* WW8_WrPlcTextBoxes::GetShapeIdArr() const
934 return &aShapeIds;
937 sal_uInt32 WW8Export::GetSdrOrdNum( const SwFrameFormat& rFormat ) const
939 sal_uInt32 nOrdNum;
940 const SdrObject* pObj = rFormat.FindRealSdrObject();
941 if( pObj )
942 nOrdNum = pObj->GetOrdNum();
943 else
945 // no Layout for this format, then recalc the ordnum
946 SwFrameFormat* pFormat = const_cast<SwFrameFormat*>(&rFormat);
947 nOrdNum = std::distance(m_pDoc->GetSpzFrameFormats()->begin(),
948 m_pDoc->GetSpzFrameFormats()->find( pFormat ) );
950 const SwDrawModel* pModel = m_pDoc->getIDocumentDrawModelAccess().GetDrawModel();
951 if( pModel )
952 nOrdNum += pModel->GetPage( 0 )->GetObjCount();
954 return nOrdNum;
957 void WW8Export::AppendFlyInFlys(const ww8::Frame& rFrameFormat,
958 const Point& rNdTopLeft)
960 OSL_ENSURE(!m_pEscher, "der EscherStream wurde schon geschrieben!");
961 if (m_pEscher)
962 return ;
963 PlcDrawObj *pDrwO;
964 if (TXT_HDFT == m_nTextTyp)
965 pDrwO = m_pHFSdrObjs;
966 else
967 pDrwO = m_pSdrObjs;
969 if (rFrameFormat.IsInline())
971 OutputField(nullptr, ww::eSHAPE, FieldString(ww::eSHAPE),
972 WRITEFIELD_START | WRITEFIELD_CMD_START | WRITEFIELD_CMD_END);
975 WW8_CP nCP = Fc2Cp(Strm().Tell());
976 bool bSuccess = pDrwO->Append(*this, nCP, rFrameFormat, rNdTopLeft);
977 OSL_ENSURE(bSuccess, "Couldn't export a graphical element!");
979 if (bSuccess)
981 static const sal_uInt8 aSpec8[] =
983 0x03, 0x6a, 0, 0, 0, 0, // sprmCObjLocation
984 0x55, 0x08, 1 // sprmCFSpec
986 // fSpec-Attribut true
987 // Fuer DrawObjets muss ein Spezial-Zeichen
988 // in den Text und darum ein fSpec-Attribut
989 m_pChpPlc->AppendFkpEntry( Strm().Tell() );
990 WriteChar( 0x8 );
991 m_pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aSpec8 ), aSpec8 );
993 //Need dummy picture frame
994 if (rFrameFormat.IsInline())
995 OutGrf(rFrameFormat);
998 if (rFrameFormat.IsInline())
999 OutputField(nullptr, ww::eSHAPE, OUString(), WRITEFIELD_CLOSE);
1002 MSWord_SdrAttrIter::MSWord_SdrAttrIter( MSWordExportBase& rWr,
1003 const EditTextObject& rEditObj, sal_uInt8 nTyp )
1004 : MSWordAttrIter( rWr ), pEditObj(&rEditObj), pEditPool(nullptr), mnTyp(nTyp)
1006 NextPara( 0 );
1009 void MSWord_SdrAttrIter::NextPara( sal_Int32 nPar )
1011 nPara = nPar;
1012 // Attributwechsel an Pos 0 wird ignoriert, da davon ausgegangen
1013 // wird, dass am Absatzanfang sowieso die Attribute neu ausgegeben
1014 // werden.
1015 aChrTextAtrArr.clear();
1016 aChrSetArr.clear();
1017 nAktSwPos = nTmpSwPos = 0;
1019 SfxItemSet aSet( pEditObj->GetParaAttribs( nPara ));
1020 pEditPool = aSet.GetPool();
1021 eNdChrSet = ItemGet<SvxFontItem>(aSet,EE_CHAR_FONTINFO).GetCharSet();
1023 if( g_pBreakIt->GetBreakIter().is() )
1024 nScript = g_pBreakIt->GetBreakIter()->getScriptType( pEditObj->GetText(nPara), 0);
1025 else
1026 nScript = i18n::ScriptType::LATIN;
1028 pEditObj->GetCharAttribs( nPara, aTextAtrArr );
1029 nAktSwPos = SearchNext( 1 );
1032 rtl_TextEncoding MSWord_SdrAttrIter::GetNextCharSet() const
1034 if( !aChrSetArr.empty() )
1035 return aChrSetArr.back();
1036 return eNdChrSet;
1039 // der erste Parameter in SearchNext() liefert zurueck, ob es ein TextAtr ist.
1040 sal_Int32 MSWord_SdrAttrIter::SearchNext( sal_Int32 nStartPos )
1042 sal_Int32 nMinPos = SAL_MAX_INT32;
1043 for(std::vector<EECharAttrib>::const_iterator i = aTextAtrArr.begin(); i < aTextAtrArr.end(); ++i)
1045 sal_Int32 nPos = i->nStart; // gibt erstes Attr-Zeichen
1046 if( nPos >= nStartPos && nPos <= nMinPos )
1048 nMinPos = nPos;
1049 SetCharSet(*i, true);
1052 nPos = i->nEnd; // gibt letztes Attr-Zeichen + 1
1053 if( nPos >= nStartPos && nPos < nMinPos )
1055 nMinPos = nPos;
1056 SetCharSet(*i, false);
1059 return nMinPos;
1062 void MSWord_SdrAttrIter::SetCharSet(const EECharAttrib& rAttr, bool bStart)
1064 const SfxPoolItem& rItem = *rAttr.pAttr;
1065 if( rItem.Which() != EE_CHAR_FONTINFO )
1067 return;
1070 if( bStart )
1072 rtl_TextEncoding eChrSet = static_cast<const SvxFontItem&>(rItem).GetCharSet();
1073 aChrSetArr.push_back( eChrSet );
1074 aChrTextAtrArr.push_back( &rAttr );
1076 else
1078 std::vector<const EECharAttrib*>::iterator it =
1079 std::find( aChrTextAtrArr.begin(), aChrTextAtrArr.end(), &rAttr );
1080 if ( it != aChrTextAtrArr.end() )
1082 aChrSetArr.erase( aChrSetArr.begin() + (it - aChrTextAtrArr.begin()) );
1083 aChrTextAtrArr.erase( it );
1088 void MSWord_SdrAttrIter::OutEEField(const SfxPoolItem& rHt)
1090 const SvxFieldItem &rField = static_cast<const SvxFieldItem &>(rHt);
1091 const SvxFieldData *pField = rField.GetField();
1092 if (pField && dynamic_cast< const SvxURLField *>( pField ) != nullptr)
1094 sal_uInt8 nOldTextTyp = m_rExport.m_nTextTyp;
1095 m_rExport.m_nTextTyp = mnTyp;
1096 const SvxURLField *pURL = static_cast<const SvxURLField *>(pField);
1097 m_rExport.AttrOutput().StartURL( pURL->GetURL(), pURL->GetTargetFrame() );
1099 const OUString &rStr = pURL->GetRepresentation();
1100 m_rExport.AttrOutput().RawText(rStr, GetNodeCharSet());
1102 m_rExport.AttrOutput().EndURL(false);
1103 m_rExport.m_nTextTyp = nOldTextTyp;
1107 void MSWord_SdrAttrIter::OutAttr( sal_Int32 nSwPos )
1109 //Collect the which ids belong to the run that we will export after
1110 //outputting the underlying paragraph attributes. We will exclude
1111 //writing these from the underlying paragraph attributes to avoid
1112 //duplicate attributes in docx export. Doesn't matter in doc
1113 //export as later props just override earlier ones.
1114 std::set<sal_uInt16> aUsedRunWhichs;
1115 if (!aTextAtrArr.empty())
1117 for(std::vector<EECharAttrib>::const_iterator i = aTextAtrArr.begin(); i < aTextAtrArr.end(); ++i)
1119 if (nSwPos >= i->nStart && nSwPos < i->nEnd)
1121 sal_uInt16 nWhich = i->pAttr->Which();
1122 aUsedRunWhichs.insert(nWhich);
1125 if( nSwPos < i->nStart )
1126 break;
1130 OutParaAttr(true, &aUsedRunWhichs);
1132 if (!aTextAtrArr.empty())
1134 const SwModify* pOldMod = m_rExport.m_pOutFormatNode;
1135 m_rExport.m_pOutFormatNode = nullptr;
1137 const SfxItemPool* pSrcPool = pEditPool;
1138 const SfxItemPool& rDstPool = m_rExport.m_pDoc->GetAttrPool();
1140 nTmpSwPos = nSwPos;
1141 // Did we already produce a <w:sz> element?
1142 m_rExport.m_bFontSizeWritten = false;
1143 for(std::vector<EECharAttrib>::const_iterator i = aTextAtrArr.begin(); i < aTextAtrArr.end(); ++i)
1145 if (nSwPos >= i->nStart && nSwPos < i->nEnd)
1147 sal_uInt16 nWhich = i->pAttr->Which();
1148 if (nWhich == EE_FEATURE_FIELD)
1150 OutEEField(*(i->pAttr));
1151 continue;
1153 if (nWhich == EE_FEATURE_TAB)
1155 m_rExport.WriteChar(0x9);
1156 continue;
1159 const sal_uInt16 nSlotId = pSrcPool->GetSlotId(nWhich);
1160 if (nSlotId && nWhich != nSlotId)
1162 nWhich = rDstPool.GetWhich(nSlotId);
1163 if (nWhich && nWhich != nSlotId &&
1164 nWhich < RES_UNKNOWNATR_BEGIN &&
1165 m_rExport.CollapseScriptsforWordOk(nScript,nWhich))
1167 // use always the SW-Which Id !
1168 SfxPoolItem* pI = i->pAttr->Clone();
1169 pI->SetWhich( nWhich );
1170 // Will this item produce a <w:sz> element?
1171 bool bFontSizeItem = nWhich == RES_CHRATR_FONTSIZE || nWhich == RES_CHRATR_CJK_FONTSIZE;
1172 if (!m_rExport.m_bFontSizeWritten || !bFontSizeItem)
1173 m_rExport.AttrOutput().OutputItem( *pI );
1174 if (bFontSizeItem)
1175 m_rExport.m_bFontSizeWritten = true;
1176 delete pI;
1181 if( nSwPos < i->nStart )
1182 break;
1184 m_rExport.m_bFontSizeWritten = false;
1186 nTmpSwPos = 0; // HasTextItem nur in dem obigen Bereich erlaubt
1187 m_rExport.m_pOutFormatNode = pOldMod;
1191 bool MSWord_SdrAttrIter::IsTextAttr(sal_Int32 nSwPos)
1193 for (std::vector<EECharAttrib>::const_iterator i = aTextAtrArr.begin(); i < aTextAtrArr.end(); ++i)
1195 if (nSwPos >= i->nStart && nSwPos < i->nEnd)
1197 if (i->pAttr->Which() == EE_FEATURE_FIELD ||
1198 i->pAttr->Which() == EE_FEATURE_TAB)
1199 return true;
1202 return false;
1205 // HasItem ist fuer die Zusammenfassung des Doppel-Attributes Underline
1206 // und WordLineMode als TextItems. OutAttr() ruft die Ausgabefunktion,
1207 // die dann ueber HasItem() nach anderen Items an der
1208 // Attribut-Anfangposition fragen kann.
1209 // Es koennen nur Attribute mit Ende abgefragt werden.
1210 // Es wird mit bDeep gesucht
1211 const SfxPoolItem* MSWord_SdrAttrIter::HasTextItem(sal_uInt16 nWhich) const
1213 nWhich = sw::hack::TransformWhichBetweenPools(*pEditPool,
1214 m_rExport.m_pDoc->GetAttrPool(), nWhich);
1215 if (nWhich)
1217 for (std::vector<EECharAttrib>::const_iterator i = aTextAtrArr.begin(); i < aTextAtrArr.end(); ++i)
1219 if (nWhich == i->pAttr->Which() && nTmpSwPos >= i->nStart && nTmpSwPos < i->nEnd)
1220 return i->pAttr; // Found
1221 if (nTmpSwPos < i->nStart)
1222 return nullptr; // dann kommt da nichts mehr
1225 return nullptr;
1228 const SfxPoolItem& MSWord_SdrAttrIter::GetItem( sal_uInt16 nWhich ) const
1230 using sw::hack::GetSetWhichFromSwDocWhich;
1231 const SfxPoolItem* pRet = HasTextItem(nWhich);
1232 if (!pRet)
1234 SfxItemSet aSet(pEditObj->GetParaAttribs(nPara));
1235 nWhich = GetSetWhichFromSwDocWhich(aSet, *m_rExport.m_pDoc, nWhich);
1236 OSL_ENSURE(nWhich, "Impossible, catastrophic failure imminent");
1237 pRet = &aSet.Get(nWhich);
1239 return *pRet;
1242 //Drawing shapes properties inherit from a different pool that the document
1243 //styles. On export to .doc[x] they will default to style "Normal". Here explicitly
1244 //set any items which are not already set, but differ from "Normal".
1245 void MSWord_SdrAttrIter::SetItemsThatDifferFromStandard(bool bCharAttr, SfxItemSet& rSet)
1247 SwTextFormatColl* pC = m_rExport.m_pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool
1248 (RES_POOLCOLL_STANDARD, false);
1250 SfxWhichIter aWhichIter(rSet);
1251 for (sal_uInt16 nEEWhich = aWhichIter.FirstWhich(); nEEWhich; nEEWhich = aWhichIter.NextWhich())
1253 if (SfxItemState::SET != rSet.GetItemState(nEEWhich, false))
1255 sal_uInt16 nSwWhich = sw::hack::TransformWhichBetweenPools(m_rExport.m_pDoc->GetAttrPool(),
1256 *pEditPool, nEEWhich);
1257 if (!nSwWhich)
1258 continue;
1259 bool bWanted = ( bCharAttr ? ( nSwWhich >= RES_CHRATR_BEGIN && nSwWhich < RES_TXTATR_END )
1260 : ( nSwWhich >= RES_PARATR_BEGIN && nSwWhich < RES_FRMATR_END ) );
1261 if (!bWanted)
1262 continue;
1264 const SfxPoolItem& rDrawItem = rSet.Get(nEEWhich);
1265 const SfxPoolItem& rStandardItem = pC->GetFormatAttr(nSwWhich);
1266 if (rDrawItem != rStandardItem)
1267 rSet.Put(rDrawItem);
1272 void MSWord_SdrAttrIter::OutParaAttr(bool bCharAttr, const std::set<sal_uInt16>* pWhichsToIgnore)
1274 SfxItemSet aSet( pEditObj->GetParaAttribs( nPara ));
1276 SetItemsThatDifferFromStandard(bCharAttr, aSet);
1278 if (aSet.Count())
1280 const SfxItemSet* pOldSet = m_rExport.GetCurItemSet();
1281 m_rExport.SetCurItemSet( &aSet );
1283 SfxItemIter aIter( aSet );
1284 const SfxPoolItem* pItem = aIter.GetCurItem();
1286 const SfxItemPool* pSrcPool = pEditPool,
1287 * pDstPool = &m_rExport.m_pDoc->GetAttrPool();
1291 sal_uInt16 nWhich = pItem->Which();
1292 if (pWhichsToIgnore && pWhichsToIgnore->find(nWhich) != pWhichsToIgnore->end())
1293 continue;
1295 sal_uInt16 nSlotId = pSrcPool->GetSlotId(nWhich);
1297 if ( nSlotId && nWhich != nSlotId &&
1298 0 != ( nWhich = pDstPool->GetWhich( nSlotId ) ) &&
1299 nWhich != nSlotId &&
1300 ( bCharAttr ? ( nWhich >= RES_CHRATR_BEGIN && nWhich < RES_TXTATR_END )
1301 : ( nWhich >= RES_PARATR_BEGIN && nWhich < RES_FRMATR_END ) ) )
1303 // use always the SW-Which Id !
1304 SfxPoolItem* pI = pItem->Clone();
1305 pI->SetWhich( nWhich );
1306 if (m_rExport.CollapseScriptsforWordOk(nScript,nWhich))
1307 m_rExport.AttrOutput().OutputItem(*pI);
1308 delete pI;
1310 } while( !aIter.IsAtEnd() && nullptr != ( pItem = aIter.NextItem() ) );
1311 m_rExport.SetCurItemSet( pOldSet );
1315 void WW8Export::WriteSdrTextObj(const SdrTextObj& rTextObj, sal_uInt8 nTyp)
1317 const OutlinerParaObject* pParaObj = nullptr;
1318 bool bOwnParaObj = false;
1321 #i13885#
1322 When the object is actively being edited, that text is not set into
1323 the objects normal text object, but lives in a separate object.
1325 if (rTextObj.IsTextEditActive())
1327 pParaObj = rTextObj.GetEditOutlinerParaObject();
1328 bOwnParaObj = true;
1330 else
1332 pParaObj = rTextObj.GetOutlinerParaObject();
1335 if( pParaObj )
1337 WriteOutliner(*pParaObj, nTyp);
1338 if( bOwnParaObj )
1339 delete pParaObj;
1343 void WW8Export::WriteOutliner(const OutlinerParaObject& rParaObj, sal_uInt8 nTyp)
1345 bool bAnyWrite = false;
1346 const EditTextObject& rEditObj = rParaObj.GetTextObject();
1347 MSWord_SdrAttrIter aAttrIter( *this, rEditObj, nTyp );
1349 sal_Int32 nPara = rEditObj.GetParagraphCount();
1350 sal_uInt8 bNul = 0;
1351 for( sal_Int32 n = 0; n < nPara; ++n )
1353 if( n )
1354 aAttrIter.NextPara( n );
1356 OSL_ENSURE( pO->empty(), " pO ist am Zeilenanfang nicht leer" );
1358 OUString aStr( rEditObj.GetText( n ));
1359 sal_Int32 nAktPos = 0;
1360 const sal_Int32 nEnd = aStr.getLength();
1361 do {
1362 const sal_Int32 nNextAttr = std::min(aAttrIter.WhereNext(), nEnd);
1364 bool bTextAtr = aAttrIter.IsTextAttr( nAktPos );
1365 if( !bTextAtr )
1366 OutSwString(aStr, nAktPos, nNextAttr - nAktPos);
1368 // Am Zeilenende werden die Attribute bis ueber das CR
1369 // aufgezogen. Ausnahme: Fussnoten am Zeilenende
1370 if( nNextAttr == nEnd && !bTextAtr )
1371 WriteCR(); // CR danach
1373 // Ausgabe der Zeichenattribute
1374 aAttrIter.OutAttr( nAktPos ); // nAktPos - 1 ??
1375 m_pChpPlc->AppendFkpEntry( Strm().Tell(),
1376 pO->size(), pO->data() );
1377 pO->clear();
1379 // Ausnahme: Fussnoten am Zeilenende
1380 if( nNextAttr == nEnd && bTextAtr )
1381 WriteCR(); // CR danach
1382 nAktPos = nNextAttr;
1383 aAttrIter.NextPos();
1385 while( nAktPos < nEnd );
1387 OSL_ENSURE( pO->empty(), " pO ist am ZeilenEnde nicht leer" );
1389 pO->push_back( bNul ); // Style # as short
1390 pO->push_back( bNul );
1392 aAttrIter.OutParaAttr(false);
1394 sal_uLong nPos = Strm().Tell();
1395 m_pPapPlc->AppendFkpEntry( Strm().Tell(),
1396 pO->size(), pO->data() );
1397 pO->clear();
1398 m_pChpPlc->AppendFkpEntry( nPos );
1401 bAnyWrite = 0 != nPara;
1402 if( !bAnyWrite )
1403 WriteStringAsPara( OUString() );
1406 void WinwordAnchoring::WriteData( EscherEx& rEx ) const
1408 //Toplevel groups get their winword extra data attached, and sub elements
1409 //use the defaults
1410 if (rEx.GetGroupLevel() <= 1)
1412 SvStream& rSt = rEx.GetStream();
1413 //The last argument denotes the number of sub properties in this atom
1414 if (mbInline)
1416 rEx.AddAtom(18, DFF_msofbtUDefProp, 3, 3); //Prop id is 0xF122
1417 rSt.WriteUInt16( 0x0390 ).WriteUInt32( 3 );
1418 rSt.WriteUInt16( 0x0392 ).WriteUInt32( 3 );
1419 //This sub property is required to be in the dummy inline frame as
1420 //well
1421 rSt.WriteUInt16( 0x053F ).WriteUInt32( nInlineHack );
1423 else
1425 rEx.AddAtom(24, DFF_msofbtUDefProp, 3, 4 ); //Prop id is 0xF122
1426 rSt.WriteUInt16( 0x038F ).WriteUInt32( mnXAlign );
1427 rSt.WriteUInt16( 0x0390 ).WriteUInt32( mnXRelTo );
1428 rSt.WriteUInt16( 0x0391 ).WriteUInt32( mnYAlign );
1429 rSt.WriteUInt16( 0x0392 ).WriteUInt32( mnYRelTo );
1434 void WW8Export::CreateEscher()
1436 SfxItemState eBackSet = m_pDoc->GetPageDesc(0).GetMaster().
1437 GetItemState(RES_BACKGROUND);
1438 if (m_pHFSdrObjs->size() || m_pSdrObjs->size() || SfxItemState::SET == eBackSet)
1440 OSL_ENSURE( !m_pEscher, "wer hat den Pointer nicht geloescht?" );
1441 SvMemoryStream* pEscherStrm = new SvMemoryStream;
1442 pEscherStrm->SetEndian(SvStreamEndian::LITTLE);
1443 m_pEscher = new SwEscherEx(pEscherStrm, *this);
1447 void WW8Export::WriteEscher()
1449 if (m_pEscher)
1451 sal_uLong nStart = pTableStrm->Tell();
1453 m_pEscher->WritePictures();
1454 m_pEscher->FinishEscher();
1456 pFib->m_fcDggInfo = nStart;
1457 pFib->m_lcbDggInfo = pTableStrm->Tell() - nStart;
1458 delete m_pEscher;
1459 m_pEscher = nullptr;
1463 void SwEscherEx::WritePictures()
1465 if( SvStream* pPicStrm = static_cast< SwEscherExGlobal& >( *mxGlobal ).GetPictureStream() )
1467 // set the blip - entries to the correct stream pos
1468 sal_Int32 nEndPos = rWrt.Strm().Tell();
1469 mxGlobal->SetNewBlipStreamOffset( nEndPos );
1471 pPicStrm->Seek( 0 );
1472 rWrt.Strm().WriteStream( *pPicStrm );
1474 Flush();
1477 // Output- Routines for Escher Export
1479 SwEscherExGlobal::SwEscherExGlobal()
1483 SwEscherExGlobal::~SwEscherExGlobal()
1487 SvStream* SwEscherExGlobal::ImplQueryPictureStream()
1489 // this function will be called exactly once
1490 mxPicStrm.reset( new SvMemoryStream );
1491 mxPicStrm->SetEndian(SvStreamEndian::LITTLE);
1492 return mxPicStrm.get();
1495 SwBasicEscherEx::SwBasicEscherEx(SvStream* pStrm, WW8Export& rWW8Wrt)
1496 : EscherEx( std::shared_ptr<EscherExGlobal>( new SwEscherExGlobal ), pStrm), rWrt(rWW8Wrt), pEscherStrm(pStrm)
1498 Init();
1501 SwBasicEscherEx::~SwBasicEscherEx()
1505 void SwBasicEscherEx::WriteFrameExtraData(const SwFrameFormat&)
1507 AddAtom(4, ESCHER_ClientAnchor);
1508 GetStream().WriteUInt32( 0x80000000 );
1511 void SwBasicEscherEx::WriteEmptyFlyFrame(const SwFrameFormat& rFormat, sal_uInt32 nShapeId)
1513 OpenContainer(ESCHER_SpContainer);
1514 AddShape(ESCHER_ShpInst_PictureFrame, 0xa00, nShapeId);
1515 // store anchor attribute
1516 WriteFrameExtraData(rFormat);
1518 AddAtom(6, DFF_msofbtUDefProp, 3, 1); //Prop id is 0xF122
1519 GetStream().WriteUInt16( 0x053F ).WriteUInt32( nInlineHack );
1521 CloseContainer(); // ESCHER_SpContainer
1524 sal_uInt32 AddMirrorFlags(sal_uInt32 nFlags, const SwMirrorGrf &rMirror)
1526 switch (rMirror.GetValue())
1528 default:
1529 case RES_MIRROR_GRAPH_DONT:
1530 break;
1531 case RES_MIRROR_GRAPH_VERT:
1532 nFlags |= SHAPEFLAG_FLIPH;
1533 break;
1534 case RES_MIRROR_GRAPH_HOR:
1535 nFlags |= SHAPEFLAG_FLIPV;
1536 break;
1537 case RES_MIRROR_GRAPH_BOTH:
1538 nFlags |= SHAPEFLAG_FLIPH;
1539 nFlags |= SHAPEFLAG_FLIPV;
1540 break;
1543 return nFlags;
1545 //For i120928,this function is added to export graphic of bullet
1546 void SwBasicEscherEx::WriteGrfBullet(const Graphic& rGrf)
1548 OpenContainer( ESCHER_SpContainer );
1549 AddShape(ESCHER_ShpInst_PictureFrame, 0xa00,0x401);
1550 EscherPropertyContainer aPropOpt;
1551 GraphicObject aGraphicObject( rGrf );
1552 OString aUniqueId = aGraphicObject.GetUniqueID();
1553 if ( !aUniqueId.isEmpty() )
1555 const MapMode aMap100mm( MapUnit::Map100thMM );
1556 Size aSize( rGrf.GetPrefSize() );
1557 if ( MapUnit::MapPixel == rGrf.GetPrefMapMode().GetMapUnit() )
1559 aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMap100mm );
1561 else
1563 aSize = OutputDevice::LogicToLogic( aSize,rGrf.GetPrefMapMode(), aMap100mm );
1565 Point aEmptyPoint;
1566 Rectangle aRect( aEmptyPoint, aSize );
1567 sal_uInt32 nBlibId = mxGlobal->GetBlibID( *(mxGlobal->QueryPictureStream()), aUniqueId,aRect );
1568 if (nBlibId)
1569 aPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, true);
1571 aPropOpt.AddOpt( ESCHER_Prop_pibFlags, ESCHER_BlipFlagDefault );
1572 aPropOpt.AddOpt( ESCHER_Prop_dyTextTop, DrawModelToEmu(0));
1573 aPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, DrawModelToEmu(0));
1574 aPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, DrawModelToEmu(0));
1575 aPropOpt.AddOpt( ESCHER_Prop_dxTextRight, DrawModelToEmu(0));
1576 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
1577 aPropOpt.AddOpt( ESCHER_Prop_dyTextTop, 0 );
1578 aPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, 0 );
1579 aPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, 0 );
1580 aPropOpt.AddOpt( ESCHER_Prop_dxTextRight, 0 );
1581 const Color aTmpColor( COL_WHITE );
1582 SvxBrushItem aBrush( aTmpColor, RES_BACKGROUND );
1583 const SvxBrushItem *pRet = rWrt.GetCurrentPageBgBrush();
1584 if (pRet && (pRet->GetGraphic() ||( pRet->GetColor() != COL_TRANSPARENT)))
1585 aBrush = *pRet;
1586 WriteBrushAttr(aBrush, aPropOpt);
1588 aPropOpt.AddOpt( ESCHER_Prop_pictureActive, 0 );
1589 aPropOpt.Commit( GetStream() );
1590 AddAtom(4, ESCHER_ClientAnchor);
1591 GetStream().WriteUInt32( 0x80000000 );
1592 CloseContainer();
1595 sal_Int32 SwBasicEscherEx::WriteGrfFlyFrame(const SwFrameFormat& rFormat, sal_uInt32 nShapeId)
1597 sal_Int32 nBorderThick=0;
1598 SwNoTextNode *pNd = GetNoTextNodeFromSwFrameFormat(rFormat);
1599 SwGrfNode *pGrfNd = pNd ? pNd->GetGrfNode() : nullptr;
1600 OSL_ENSURE(pGrfNd, "No SwGrfNode ?, suspicious");
1601 if (!pGrfNd)
1602 return nBorderThick;
1604 OpenContainer( ESCHER_SpContainer );
1606 const SwMirrorGrf &rMirror = pGrfNd->GetSwAttrSet().GetMirrorGrf();
1607 AddShape(ESCHER_ShpInst_PictureFrame, AddMirrorFlags(0xa00, rMirror),
1608 nShapeId);
1610 EscherPropertyContainer aPropOpt;
1612 sal_uInt32 nFlags = ESCHER_BlipFlagDefault;
1614 if (pGrfNd->IsLinkedFile())
1616 OUString sURL;
1617 pGrfNd->GetFileFilterNms( &sURL, nullptr );
1619 ww::bytes aBuf;
1620 SwWW8Writer::InsAsString16( aBuf, sURL );
1621 SwWW8Writer::InsUInt16( aBuf, 0 );
1623 sal_uInt16 nArrLen = aBuf.size();
1624 sal_uInt8* pArr = new sal_uInt8[ nArrLen ];
1625 std::copy( aBuf.begin(), aBuf.end(), pArr);
1627 aPropOpt.AddOpt(ESCHER_Prop_pibName, true, nArrLen, pArr, nArrLen);
1628 nFlags = ESCHER_BlipFlagLinkToFile | ESCHER_BlipFlagURL |
1629 ESCHER_BlipFlagDoNotSave;
1631 else
1633 Graphic aGraphic(pGrfNd->GetGrf());
1634 GraphicObject aGraphicObject( aGraphic );
1635 OString aUniqueId = aGraphicObject.GetUniqueID();
1637 if (!aUniqueId.isEmpty())
1639 const MapMode aMap100mm( MapUnit::Map100thMM );
1640 Size aSize( aGraphic.GetPrefSize() );
1642 if ( MapUnit::MapPixel == aGraphic.GetPrefMapMode().GetMapUnit() )
1644 aSize = Application::GetDefaultDevice()->PixelToLogic(
1645 aSize, aMap100mm );
1647 else
1649 aSize = OutputDevice::LogicToLogic( aSize,
1650 aGraphic.GetPrefMapMode(), aMap100mm );
1653 Point aEmptyPoint;
1654 Rectangle aRect( aEmptyPoint, aSize );
1656 sal_uInt32 nBlibId = mxGlobal->GetBlibID( *QueryPictureStream(),
1657 aUniqueId, aRect );
1658 if (nBlibId)
1659 aPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, true);
1663 aPropOpt.AddOpt( ESCHER_Prop_pibFlags, nFlags );
1664 nBorderThick = WriteFlyFrameAttr(rFormat,mso_sptPictureFrame,aPropOpt);
1665 WriteGrfAttr(*pGrfNd, rFormat, aPropOpt);
1667 aPropOpt.Commit( GetStream() );
1669 // store anchor attribute
1670 WriteFrameExtraData( rFormat );
1672 CloseContainer(); // ESCHER_SpContainer
1673 return nBorderThick;
1676 void SwBasicEscherEx::WriteGrfAttr(const SwNoTextNode& rNd, const SwFrameFormat& rFormat,
1677 EscherPropertyContainer& rPropOpt)
1679 const SfxPoolItem* pItem;
1680 sal_uInt32 nMode = GRAPHICDRAWMODE_STANDARD;
1681 sal_Int32 nContrast = 0;
1682 sal_Int16 nBrightness = 0;
1684 if (SfxItemState::SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_CONTRAST,
1685 true, &pItem))
1687 nContrast = static_cast<const SfxInt16Item*>(pItem)->GetValue();
1690 if (SfxItemState::SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_LUMINANCE,
1691 true, &pItem))
1693 nBrightness = static_cast<const SfxInt16Item*>(pItem)->GetValue();
1696 if (SfxItemState::SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_DRAWMODE,
1697 true, &pItem))
1699 nMode = static_cast<const SfxEnumItem*>(pItem)->GetValue();
1700 if (nMode == GRAPHICDRAWMODE_WATERMARK)
1703 There is no real watermark mode in word, we must use standard
1704 mode and modify our ones by 70% extra brightness and 70% less
1705 contrast. This means that unmodified default OOo watermark
1706 will turn back into watermark, and modified OOo watermark will
1707 change into a close visual representation in standardmode
1709 nBrightness += 70;
1710 if (nBrightness > 100)
1711 nBrightness = 100;
1712 nContrast -= 70;
1713 if (nContrast < -100)
1714 nContrast = -100;
1715 nMode = GRAPHICDRAWMODE_STANDARD;
1719 if (nMode == GRAPHICDRAWMODE_GREYS)
1720 nMode = 0x40004;
1721 else if (nMode == GRAPHICDRAWMODE_MONO)
1722 nMode = 0x60006;
1723 else
1724 nMode = 0;
1725 rPropOpt.AddOpt( ESCHER_Prop_pictureActive, nMode );
1727 if (nContrast != 0)
1729 nContrast+=100;
1730 if (nContrast == 100)
1731 nContrast = 0x10000;
1732 else if (nContrast < 100)
1734 nContrast *= 0x10000;
1735 nContrast /= 100;
1737 else if (nContrast < 200)
1738 nContrast = (100 * 0x10000) / (200-nContrast);
1739 else
1740 nContrast = 0x7fffffff;
1741 rPropOpt.AddOpt( ESCHER_Prop_pictureContrast, nContrast);
1744 if (nBrightness != 0)
1745 rPropOpt.AddOpt( ESCHER_Prop_pictureBrightness, nBrightness * 327 );
1747 sal_Int32 nCropL = 0;
1748 sal_Int32 nCropR = 0;
1749 sal_Int32 nCropT = 0;
1750 sal_Int32 nCropB = 0;
1751 if (SfxItemState::SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_CROPGRF,
1752 true, &pItem))
1754 const SwCropGrf& rCrop = *static_cast<const SwCropGrf*>(pItem);
1755 nCropL += rCrop.GetLeft();
1756 nCropR += rCrop.GetRight();
1757 nCropT += rCrop.GetTop();
1758 nCropB += rCrop.GetBottom();
1761 // simulate border padding as a negative crop.
1762 if (SfxItemState::SET == rFormat.GetItemState(RES_BOX, false, &pItem))
1764 const SvxBoxItem& rBox = *static_cast<const SvxBoxItem*>(pItem);
1765 nCropL -= rBox.GetDistance( SvxBoxItemLine::LEFT );
1766 nCropR -= rBox.GetDistance( SvxBoxItemLine::RIGHT );
1767 nCropT -= rBox.GetDistance( SvxBoxItemLine::TOP );
1768 nCropB -= rBox.GetDistance( SvxBoxItemLine::BOTTOM );
1771 const Size aSz( rNd.GetTwipSize() );
1772 if( 0 != nCropL )
1773 rPropOpt.AddOpt( ESCHER_Prop_cropFromLeft, ToFract16( nCropL, aSz.Width()) );
1774 if( 0 != nCropR )
1775 rPropOpt.AddOpt( ESCHER_Prop_cropFromRight, ToFract16( nCropR, aSz.Width()));
1776 if( 0 != nCropT )
1777 rPropOpt.AddOpt( ESCHER_Prop_cropFromTop, ToFract16( nCropT, aSz.Height()));
1778 if( 0 != nCropB )
1779 rPropOpt.AddOpt( ESCHER_Prop_cropFromBottom, ToFract16( nCropB, aSz.Height()));
1782 void SwBasicEscherEx::SetPicId(const SdrObject &, sal_uInt32,
1783 EscherPropertyContainer &)
1787 void SwEscherEx::SetPicId(const SdrObject &rSdrObj, sal_uInt32 nShapeId,
1788 EscherPropertyContainer &rPropOpt)
1790 pTextBxs->Append(rSdrObj, nShapeId);
1791 sal_uInt32 nPicId = pTextBxs->Count();
1792 nPicId *= 0x10000;
1793 rPropOpt.AddOpt( ESCHER_Prop_pictureId, nPicId );
1796 sal_Int32 SwBasicEscherEx::WriteOLEFlyFrame(const SwFrameFormat& rFormat, sal_uInt32 nShapeId)
1798 sal_Int32 nBorderThick = 0;
1799 if (const SdrObject* pSdrObj = rFormat.FindRealSdrObject())
1801 SwNodeIndex aIdx(*rFormat.GetContent().GetContentIdx(), 1);
1802 SwOLENode& rOLENd = *aIdx.GetNode().GetOLENode();
1803 sal_Int64 nAspect = rOLENd.GetAspect();
1805 uno::Reference < embed::XEmbeddedObject > xObj(rOLENd.GetOLEObj().GetOleRef());
1807 // the rectangle is used to transport the size of the object
1808 // the left, top corner is set to ( 0, 0 ) by default constructor,
1809 // if the width and height are set correctly bRectIsSet should be set to true
1810 awt::Rectangle aRect;
1811 bool bRectIsSet = false;
1813 // TODO/LATER: should the icon size be stored in case of iconified object?
1814 if ( xObj.is() && nAspect != embed::Aspects::MSOLE_ICON )
1818 awt::Size aSize = xObj->getVisualAreaSize( nAspect );
1819 aRect.Width = aSize.Width;
1820 aRect.Height = aSize.Height;
1821 bRectIsSet = true;
1823 catch( const uno::Exception& )
1828 #i5970#
1829 Export floating ole2 .doc ver 8+ wmf ole2 previews as emf previews
1830 instead ==> allows unicode text to be preserved
1832 #ifdef OLE_PREVIEW_AS_EMF
1833 const Graphic* pGraphic = rOLENd.GetGraphic();
1834 #endif
1835 OpenContainer(ESCHER_SpContainer);
1837 EscherPropertyContainer aPropOpt;
1838 const SwMirrorGrf &rMirror = rOLENd.GetSwAttrSet().GetMirrorGrf();
1839 WriteOLEPicture(aPropOpt, AddMirrorFlags(0xa00 | SHAPEFLAG_OLESHAPE,
1840 rMirror), pGraphic ? *pGraphic : Graphic(), *pSdrObj, nShapeId, bRectIsSet ? &aRect : nullptr );
1842 nBorderThick = WriteFlyFrameAttr(rFormat, mso_sptPictureFrame, aPropOpt);
1843 WriteGrfAttr(rOLENd, rFormat, aPropOpt);
1844 aPropOpt.Commit(GetStream());
1846 // store anchor attribute
1847 WriteFrameExtraData( rFormat );
1849 CloseContainer(); // ESCHER_SpContainer
1851 return nBorderThick;
1854 void SwBasicEscherEx::WriteBrushAttr(const SvxBrushItem &rBrush,
1855 EscherPropertyContainer& rPropOpt)
1857 bool bSetOpacity = false;
1858 sal_uInt32 nOpaque = 0;
1859 if (const GraphicObject *pGraphicObject = rBrush.GetGraphicObject())
1861 OString aUniqueId = pGraphicObject->GetUniqueID();
1862 if (!aUniqueId.isEmpty())
1864 const Graphic &rGraphic = pGraphicObject->GetGraphic();
1865 Size aSize(rGraphic.GetPrefSize());
1866 const MapMode aMap100mm(MapUnit::Map100thMM);
1867 if (MapUnit::MapPixel == rGraphic.GetPrefMapMode().GetMapUnit())
1869 aSize = Application::GetDefaultDevice()->PixelToLogic(
1870 aSize, aMap100mm);
1872 else
1874 aSize = OutputDevice::LogicToLogic(aSize,
1875 rGraphic.GetPrefMapMode(), aMap100mm);
1878 Point aEmptyPoint;
1879 Rectangle aRect(aEmptyPoint, aSize);
1881 sal_uInt32 nBlibId = mxGlobal->GetBlibID( *QueryPictureStream(),
1882 aUniqueId, aRect);
1883 if (nBlibId)
1884 rPropOpt.AddOpt(ESCHER_Prop_fillBlip,nBlibId,true);
1887 if (0 != (nOpaque = pGraphicObject->GetAttr().GetTransparency()))
1888 bSetOpacity = true;
1890 rPropOpt.AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
1891 rPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
1892 rPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0 );
1894 else
1896 sal_uInt32 nFillColor = GetColor(rBrush.GetColor(), false);
1897 rPropOpt.AddOpt( ESCHER_Prop_fillColor, nFillColor );
1898 rPropOpt.AddOpt( ESCHER_Prop_fillBackColor, nFillColor ^ 0xffffff );
1899 rPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100010 );
1901 if (0 != (nOpaque = rBrush.GetColor().GetTransparency()))
1902 bSetOpacity = true;
1905 if (bSetOpacity)
1907 nOpaque = (nOpaque * 100) / 0xFE;
1908 nOpaque = ((100 - nOpaque) << 16) / 100;
1909 rPropOpt.AddOpt(ESCHER_Prop_fillOpacity, nOpaque);
1913 sal_Int32 SwBasicEscherEx::WriteFlyFrameAttr(const SwFrameFormat& rFormat,
1914 MSO_SPT eShapeType, EscherPropertyContainer& rPropOpt)
1916 sal_Int32 nLineWidth=0;
1917 const SfxPoolItem* pItem;
1918 bool bFirstLine = true;
1919 if (SfxItemState::SET == rFormat.GetItemState(RES_BOX, true, &pItem))
1921 static const o3tl::enumarray<SvxBoxItemLine, sal_uInt16> aExhperProp =
1923 ESCHER_Prop_dyTextTop, ESCHER_Prop_dyTextBottom,
1924 ESCHER_Prop_dxTextLeft, ESCHER_Prop_dxTextRight
1926 const SvxBorderLine* pLine;
1928 for( SvxBoxItemLine n : o3tl::enumrange<SvxBoxItemLine>() )
1929 if( nullptr != ( pLine = static_cast<const SvxBoxItem*>(pItem)->GetLine( n )) )
1931 if( bFirstLine )
1933 sal_uInt32 nLineColor = GetColor(pLine->GetColor(), false);
1934 rPropOpt.AddOpt( ESCHER_Prop_lineColor, nLineColor );
1935 rPropOpt.AddOpt( ESCHER_Prop_lineBackColor,
1936 nLineColor ^ 0xffffff );
1938 MSO_LineStyle eStyle;
1939 if( pLine->isDouble() )
1941 // double line
1942 nLineWidth = pLine->GetWidth();
1943 if( pLine->GetInWidth() == pLine->GetOutWidth() )
1944 eStyle = mso_lineDouble;
1945 else if( pLine->GetInWidth() < pLine->GetOutWidth() )
1946 eStyle = mso_lineThickThin;
1947 else
1948 eStyle = mso_lineThinThick;
1950 else
1952 // simple line
1953 eStyle = mso_lineSimple;
1954 nLineWidth = pLine->GetWidth();
1957 rPropOpt.AddOpt( ESCHER_Prop_lineStyle, eStyle );
1958 rPropOpt.AddOpt( ESCHER_Prop_lineWidth,
1959 DrawModelToEmu( nLineWidth ));
1961 MSO_LineDashing eDashing = mso_lineSolid;
1962 switch (pLine->GetBorderLineStyle())
1964 case table::BorderLineStyle::DASHED:
1965 eDashing = mso_lineDashGEL;
1966 break;
1967 case table::BorderLineStyle::DOTTED:
1968 eDashing = mso_lineDotGEL;
1969 break;
1970 case table::BorderLineStyle::SOLID:
1971 default:
1972 break;
1974 rPropOpt.AddOpt( ESCHER_Prop_lineDashing, eDashing );
1975 rPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x8000E );
1977 //Use import logic to determine how much of border will go
1978 //outside graphic
1979 nLineWidth = SwMSDffManager::GetEscherLineMatch(
1980 eStyle,eShapeType,nLineWidth);
1981 bFirstLine = false;
1983 rPropOpt.AddOpt( aExhperProp[ n ], DrawModelToEmu(
1984 static_cast<const SvxBoxItem*>(pItem)->GetDistance( n ) ));
1986 else
1987 rPropOpt.AddOpt( aExhperProp[ n ], DrawModelToEmu(static_cast<const SvxBoxItem*>(pItem)->GetDistance( n )) );
1989 else
1991 rPropOpt.AddOpt( ESCHER_Prop_dyTextTop, 0 );
1992 rPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, 0 );
1993 rPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, 0 );
1994 rPropOpt.AddOpt( ESCHER_Prop_dxTextRight, 0 );
1997 if( bFirstLine ) // no valid line found
1999 rPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
2001 const SwAttrSet& rAttrSet = rFormat.GetAttrSet();
2002 if (SfxItemState::SET == rAttrSet.GetItemState(RES_BOX, false, &pItem))
2004 const SvxBoxItem* pBox = static_cast<const SvxBoxItem*>(pItem);
2005 if( pBox )
2007 const SfxPoolItem* pShadItem;
2008 if (SfxItemState::SET
2009 == rAttrSet.GetItemState(RES_SHADOW, true, &pShadItem))
2011 const SvxShadowItem* pSI = static_cast<const SvxShadowItem*>(pShadItem);
2013 const sal_uInt16 nCstScale = 635; // unit scale between AOO and MS Word
2014 const sal_uInt32 nShadowType = 131074; // shadow type of ms word. need to set the default value.
2016 sal_uInt32 nColor = (sal_uInt32)(pSI->GetColor().GetColor()) ;
2017 sal_Int32 nOffX = pSI->GetWidth() * nCstScale;
2018 sal_Int32 nOffY = pSI->GetWidth() * nCstScale;
2019 sal_uInt32 nShadow = nShadowType;
2021 SvxShadowLocation eLocation = pSI->GetLocation();
2022 if( (eLocation!=SVX_SHADOW_NONE) && (pSI->GetWidth()!=0) )
2024 switch( eLocation )
2026 case SVX_SHADOW_TOPLEFT:
2028 nOffX = -nOffX;
2029 nOffY = -nOffY;
2031 break;
2032 case SVX_SHADOW_TOPRIGHT:
2034 nOffY = -nOffY;
2036 break;
2037 case SVX_SHADOW_BOTTOMLEFT:
2039 nOffX = -nOffX;
2041 break;
2042 case SVX_SHADOW_BOTTOMRIGHT:
2043 break;
2044 default:
2045 break;
2048 rPropOpt.AddOpt( DFF_Prop_shadowColor, wwUtility::RGBToBGR((nColor)));
2049 rPropOpt.AddOpt( DFF_Prop_shadowOffsetX, nOffX );
2050 rPropOpt.AddOpt( DFF_Prop_shadowOffsetY, nOffY );
2051 rPropOpt.AddOpt( DFF_Prop_fshadowObscured, nShadow );
2057 // SwWW8ImplReader::Read_GrafLayer() imports these as opaque
2058 // unconditionally, so if both are true, don't export the property.
2059 bool bIsInHeader = sw::IsFlyFrameFormatInHeader(rFormat);
2060 bool bIsThrought = rFormat.GetSurround().GetValue() == SURROUND_THROUGHT;
2062 if (bIsInHeader)
2064 SvxBrushItem aBrush(rFormat.makeBackgroundBrushItem());
2065 WriteBrushAttr(aBrush, rPropOpt);
2067 else
2069 SvxBrushItem aBrush(rWrt.TrueFrameBgBrush(rFormat));
2070 WriteBrushAttr(aBrush, rPropOpt);
2073 const SdrObject* pObj = rFormat.FindRealSdrObject();
2075 if( pObj && (pObj->GetLayer() == GetHellLayerId() ||
2076 pObj->GetLayer() == GetInvisibleHellId() ) && !(bIsInHeader && bIsThrought))
2078 rPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 );
2081 PreWriteHyperlinkWithinFly(rFormat,rPropOpt);
2083 return nLineWidth;
2086 sal_Int32 SwEscherEx::WriteFlyFrameAttr(const SwFrameFormat& rFormat, MSO_SPT eShapeType,
2087 EscherPropertyContainer& rPropOpt)
2089 sal_Int32 nLineWidth = SwBasicEscherEx::WriteFlyFrameAttr(rFormat, eShapeType,
2090 rPropOpt);
2093 These are not in SwBasicEscherEx::WriteFlyFrameAttr because inline objs
2094 can't do it in word and it hacks it in by stretching the graphic that
2095 way, perhaps we should actually draw in this space into the graphic we
2096 are exporting!
2098 const SfxPoolItem* pItem;
2099 if (SfxItemState::SET == rFormat.GetItemState(RES_LR_SPACE, true, &pItem))
2101 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft,
2102 DrawModelToEmu( static_cast<const SvxLRSpaceItem*>(pItem)->GetLeft() ) );
2103 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight,
2104 DrawModelToEmu( static_cast<const SvxLRSpaceItem*>(pItem)->GetRight() ) );
2106 else
2108 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft, 0 );
2109 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight, 0 );
2112 if (SfxItemState::SET == rFormat.GetItemState(RES_UL_SPACE, true, &pItem))
2114 rPropOpt.AddOpt( ESCHER_Prop_dyWrapDistTop,
2115 DrawModelToEmu( static_cast<const SvxULSpaceItem*>(pItem)->GetUpper() ) );
2116 rPropOpt.AddOpt( ESCHER_Prop_dyWrapDistBottom,
2117 DrawModelToEmu( static_cast<const SvxULSpaceItem*>(pItem)->GetLower() ) );
2120 if (rFormat.GetSurround().IsContour())
2122 if (const SwNoTextNode *pNd = GetNoTextNodeFromSwFrameFormat(rFormat))
2124 const tools::PolyPolygon *pPolyPoly = pNd->HasContour();
2125 if (pPolyPoly && pPolyPoly->Count())
2127 tools::Polygon aPoly = CorrectWordWrapPolygonForExport(*pPolyPoly, pNd);
2128 SvMemoryStream aPolyDump;
2129 aPolyDump.SetEndian(SvStreamEndian::LITTLE);
2131 sal_uInt16 nLen = aPoly.GetSize();
2132 aPolyDump.WriteUInt16( nLen );
2133 aPolyDump.WriteUInt16( nLen );
2134 aPolyDump.WriteUInt16( 8 );
2135 for (sal_uInt16 nI = 0; nI < nLen; ++nI)
2137 aPolyDump.WriteUInt32( aPoly[nI].X() );
2138 aPolyDump.WriteUInt32( aPoly[nI].Y() );
2141 sal_uInt16 nArrLen = msword_cast<sal_uInt16>(aPolyDump.Tell());
2142 void *pArr = const_cast<void *>(aPolyDump.GetData());
2143 //PropOpt wants to own the buffer
2144 aPolyDump.ObjectOwnsMemory(false);
2145 rPropOpt.AddOpt(DFF_Prop_pWrapPolygonVertices, false,
2146 nArrLen, static_cast<sal_uInt8 *>(pArr), nArrLen);
2151 PreWriteHyperlinkWithinFly(rFormat,rPropOpt);
2153 return nLineWidth;
2156 void SwBasicEscherEx::Init()
2158 MapUnit eMap = MapUnit::MapTwip;
2159 if (SwDrawModel *pModel = rWrt.m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
2161 // PPT arbeitet nur mit Einheiten zu 576DPI
2162 // WW hingegen verwendet twips, dh. 1440DPI.
2163 eMap = pModel->GetScaleUnit();
2166 // MS-DFF-Properties sind grossteils in EMU (English Metric Units) angegeben
2167 // 1mm=36000emu, 1twip=635emu
2168 Fraction aFact(360, 1);
2169 aFact /= GetMapFactor(MapUnit::Map100thMM, eMap).X();
2170 // create little values
2171 aFact = Fraction(aFact.GetNumerator(), aFact.GetDenominator());
2172 mnEmuMul = aFact.GetNumerator();
2173 mnEmuDiv = aFact.GetDenominator();
2175 SetHellLayerId(rWrt.m_pDoc->getIDocumentDrawModelAccess().GetHellId());
2178 sal_Int32 SwBasicEscherEx::ToFract16(sal_Int32 nVal, sal_uInt32 nMax)
2180 if (nMax)
2182 if (nVal >= 0)
2184 sal_Int32 nMSVal = (nVal / 65536) * nMax;
2185 nMSVal += (nVal * 65536) / nMax;
2186 return nMSVal;
2187 } else {
2188 // negative fraction does not have "-0", fractional part is always
2189 // positive: -0.4 represented as -1 + 0.6
2190 sal_Int32 const nDiv = (nVal / sal_Int32(nMax)) - 1;
2191 sal_uInt32 nMSVal = (sal_uInt32(nDiv) << 16) & 0xffff0000;
2192 nMSVal += (nVal * 65536) / sal_Int32(nMax) + (-nDiv * 65536);
2193 return nMSVal;
2196 return 0;
2199 SdrLayerID SwBasicEscherEx::GetInvisibleHellId() const
2201 return rWrt.m_pDoc->getIDocumentDrawModelAccess().GetInvisibleHellId();
2204 void SwBasicEscherEx::WritePictures()
2206 if( SvStream* pPicStrm = static_cast< SwEscherExGlobal& >( *mxGlobal ).GetPictureStream() )
2208 // set the blip - entries to the correct stream pos
2209 sal_Int32 nEndPos = pPicStrm->Tell();
2210 mxGlobal->WriteBlibStoreEntry(*pEscherStrm, 1, true, nEndPos);
2212 pPicStrm->Seek(0);
2213 pEscherStrm->WriteStream( *pPicStrm );
2217 SwEscherEx::SwEscherEx(SvStream* pStrm, WW8Export& rWW8Wrt)
2218 : SwBasicEscherEx(pStrm, rWW8Wrt),
2219 pTextBxs(nullptr)
2221 aHostData.SetClientData(&aWinwordAnchoring);
2222 OpenContainer( ESCHER_DggContainer );
2224 sal_uInt16 nColorCount = 4;
2225 pStrm ->WriteUInt16( nColorCount << 4 ) // instance
2226 .WriteUInt16( ESCHER_SplitMenuColors ) // record type
2227 .WriteUInt32( nColorCount * 4 ) // size
2228 .WriteUInt32( 0x08000004 )
2229 .WriteUInt32( 0x08000001 )
2230 .WriteUInt32( 0x08000002 )
2231 .WriteUInt32( 0x100000f7 );
2233 CloseContainer(); // ESCHER_DggContainer
2235 sal_uInt8 i = 2; // for header/footer and the other
2236 PlcDrawObj *pSdrObjs = rWrt.m_pHFSdrObjs;
2237 pTextBxs = rWrt.m_pHFTextBxs;
2239 // if no header/footer -> skip over
2240 if (!pSdrObjs->size())
2242 --i;
2243 pSdrObjs = rWrt.m_pSdrObjs;
2244 pTextBxs = rWrt.m_pTextBxs;
2247 for( ; i--; pSdrObjs = rWrt.m_pSdrObjs, pTextBxs = rWrt.m_pTextBxs )
2249 // "dummy char" (or any Count ?) - why? Only Microsoft knows it.
2250 GetStream().WriteChar( i );
2252 OpenContainer( ESCHER_DgContainer );
2254 EnterGroup();
2256 sal_uLong nSecondShapeId = pSdrObjs == rWrt.m_pSdrObjs ? GenerateShapeId() : 0;
2258 // write now all Writer-/DrawObjects
2259 DrawObjPointerVector aSorted;
2260 MakeZOrderArrAndFollowIds(pSdrObjs->GetObjArr(), aSorted);
2262 sal_uInt32 nShapeId=0;
2263 DrawObjPointerIter aEnd = aSorted.end();
2264 for (DrawObjPointerIter aIter = aSorted.begin(); aIter != aEnd; ++aIter)
2266 sal_Int32 nBorderThick=0;
2267 DrawObj *pObj = (*aIter);
2268 OSL_ENSURE(pObj, "impossible");
2269 if (!pObj)
2270 continue;
2271 const ww8::Frame &rFrame = pObj->maContent;
2272 const SwFrameFormat& rFormat = rFrame.GetFrameFormat();
2274 switch (rFrame.GetWriterType())
2276 case ww8::Frame::eTextBox:
2277 case ww8::Frame::eOle:
2278 case ww8::Frame::eGraphic:
2279 nBorderThick = WriteFlyFrame(*pObj, nShapeId, aSorted);
2280 break;
2281 case ww8::Frame::eFormControl:
2282 WriteOCXControl(rFormat, nShapeId = GenerateShapeId());
2283 break;
2284 case ww8::Frame::eDrawing:
2286 aWinwordAnchoring.SetAnchoring(rFormat);
2287 const SdrObject* pSdrObj = rFormat.FindRealSdrObject();
2288 if (pSdrObj)
2290 bool bSwapInPage = false;
2291 if (!pSdrObj->GetPage())
2293 if (SwDrawModel* pModel = rWrt.m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
2295 if (SdrPage *pPage = pModel->GetPage(0))
2297 bSwapInPage = true;
2298 (const_cast<SdrObject*>(pSdrObj))->SetPage(pPage);
2303 nShapeId = AddSdrObject(*pSdrObj);
2305 if (bSwapInPage)
2306 (const_cast<SdrObject*>(pSdrObj))->SetPage(nullptr);
2308 #if OSL_DEBUG_LEVEL > 0
2309 else
2310 OSL_ENSURE( false, "Where is the SDR-Object?" );
2311 #endif
2313 break;
2314 default:
2315 break;
2318 if( !nShapeId )
2320 nShapeId = AddDummyShape();
2323 pObj->SetShapeDetails(nShapeId, nBorderThick);
2326 EndSdrObjectPage(); // ???? Bugfix for 74724
2328 if( nSecondShapeId )
2330 OpenContainer( ESCHER_SpContainer );
2332 AddShape( ESCHER_ShpInst_Rectangle, 0xe00, nSecondShapeId );
2334 EscherPropertyContainer aPropOpt;
2335 const SwFrameFormat &rFormat = rWrt.m_pDoc->GetPageDesc(0).GetMaster();
2336 const SfxPoolItem* pItem = nullptr;
2337 SfxItemState eState = rFormat.GetItemState(RES_BACKGROUND, true,
2338 &pItem);
2339 if (SfxItemState::SET == eState && pItem)
2341 const SvxBrushItem* pBrush = static_cast<const SvxBrushItem*>(pItem);
2342 WriteBrushAttr(*pBrush, aPropOpt);
2344 SvxGraphicPosition ePos = pBrush->GetGraphicPos();
2345 if( ePos != GPOS_NONE && ePos != GPOS_AREA )
2347 /* #i56806# 0x033F parameter specifies a 32-bit field of shape boolean properties.
2348 0x10001 means fBackground and fUsefBackground flag are true thus background
2349 picture will be shown as "tiled" fill.*/
2350 aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 );
2353 aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x8000001 );
2354 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080008 );
2355 aPropOpt.AddOpt( ESCHER_Prop_shadowColor, 0x8000002 );
2356 aPropOpt.AddOpt( ESCHER_Prop_lineWidth, 0 );
2358 aPropOpt.Commit( *pStrm );
2360 AddAtom( 4, ESCHER_ClientData );
2361 GetStream().WriteInt32( 1 );
2363 CloseContainer(); // ESCHER_SpContainer
2365 CloseContainer(); // ESCHER_DgContainer
2369 SwEscherEx::~SwEscherEx()
2373 void SwEscherEx::FinishEscher()
2375 pEscherStrm->Seek(0);
2376 rWrt.pTableStrm->WriteStream( *pEscherStrm );
2377 delete pEscherStrm;
2378 pEscherStrm = nullptr;
2381 /** method to perform conversion of positioning attributes with the help
2382 of corresponding layout information
2384 #i30669#
2385 Because most of the Writer object positions doesn't correspond to the
2386 object positions in WW8, this method converts the positioning
2387 attributes. For this conversion the corresponding layout information
2388 is needed. If no layout information exists - e.g. no layout exists - no
2389 conversion is performed.
2390 No conversion is performed for as-character anchored objects. Whose
2391 object positions are already treated special in method <WriteData(..)>.
2393 @param _iorHoriOri
2394 input/output parameter - containing the current horizontal position
2395 attributes, which are converted by this method.
2397 @param _iorVertOri
2398 input/output parameter - containing the current vertical position
2399 attributes, which are converted by this method.
2401 @param _rFrameFormat
2402 input parameter - frame format of the anchored object
2404 @return boolean, indicating, if a conversion has been performed.
2406 bool WinwordAnchoring::ConvertPosition( SwFormatHoriOrient& _iorHoriOri,
2407 SwFormatVertOrient& _iorVertOri,
2408 const SwFrameFormat& _rFrameFormat )
2410 const RndStdIds eAnchor = _rFrameFormat.GetAnchor().GetAnchorId();
2412 if ( (FLY_AS_CHAR == eAnchor) || (FLY_AT_FLY == eAnchor) )
2414 // no conversion for as-character or at frame anchored objects
2415 return false;
2418 // determine anchored object
2419 SwAnchoredObject* pAnchoredObj( nullptr );
2421 const SwContact* pContact = _rFrameFormat.FindContactObj();
2422 if ( pContact )
2424 std::list<SwAnchoredObject*> aAnchoredObjs;
2425 pContact->GetAnchoredObjs( aAnchoredObjs );
2426 if ( !aAnchoredObjs.empty() )
2428 pAnchoredObj = aAnchoredObjs.front();
2432 if ( !pAnchoredObj )
2434 // no anchored object found. Thus, the needed layout information can't
2435 // be determined. --> no conversion
2436 return false;
2438 // no conversion for anchored drawing object, which aren't attached to an
2439 // anchor frame.
2440 // This is the case for drawing objects, which are anchored inside a page
2441 // header/footer of an *unused* page style.
2442 if ( dynamic_cast<SwAnchoredDrawObject*>(pAnchoredObj) &&
2443 !pAnchoredObj->GetAnchorFrame() )
2445 return false;
2448 bool bConverted( false );
2450 // determine value of attribute 'Follow text flow', because positions aligned
2451 // at page areas have to be converted, if it's set.
2452 const bool bFollowTextFlow = _rFrameFormat.GetFollowTextFlow().GetValue();
2454 // check, if horizontal and vertical position have to be converted due to
2455 // the fact, that the object is anchored at a paragraph, which has a "column
2456 // break before" attribute
2457 bool bConvDueToAnchoredAtColBreakPara( false );
2458 if ( ( (eAnchor == FLY_AT_PARA) || (eAnchor == FLY_AT_CHAR) ) &&
2459 _rFrameFormat.GetAnchor().GetContentAnchor() &&
2460 _rFrameFormat.GetAnchor().GetContentAnchor()->nNode.GetNode().IsTextNode() )
2462 SwTextNode& rAnchorTextNode =
2463 dynamic_cast<SwTextNode&>(_rFrameFormat.GetAnchor().GetContentAnchor()->nNode.GetNode());
2464 const SvxFormatBreakItem* pBreak = &(ItemGet<SvxFormatBreakItem>(rAnchorTextNode, RES_BREAK));
2465 if ( pBreak &&
2466 pBreak->GetBreak() == SvxBreak::ColumnBefore )
2468 bConvDueToAnchoredAtColBreakPara = true;
2472 // convert horizontal position, if needed
2474 enum HoriConv { NO_CONV, CONV2PG, CONV2COL, CONV2CHAR };
2475 HoriConv eHoriConv( NO_CONV );
2477 // determine, if conversion has to be performed due to the position orientation
2478 bool bConvDueToOrientation( false );
2480 const sal_Int16 eHOri = _iorHoriOri.GetHoriOrient();
2481 bConvDueToOrientation = eHOri == text::HoriOrientation::LEFT || eHOri == text::HoriOrientation::RIGHT ||
2482 eHOri == text::HoriOrientation::INSIDE || eHOri == text::HoriOrientation::OUTSIDE ||
2483 ( eHOri != text::HoriOrientation::CENTER && _iorHoriOri.IsPosToggle() );
2486 // determine conversion type due to the position relation
2487 if ( bConvDueToAnchoredAtColBreakPara )
2489 eHoriConv = CONV2PG;
2491 else if ( _iorHoriOri.IsPosToggle()
2492 && _iorHoriOri.GetHoriOrient() == text::HoriOrientation::RIGHT )
2494 eHoriConv = NO_CONV;
2495 _iorHoriOri.SetHoriOrient( text::HoriOrientation::OUTSIDE );
2497 else
2499 switch ( _iorHoriOri.GetRelationOrient() )
2501 case text::RelOrientation::PAGE_FRAME:
2502 case text::RelOrientation::PAGE_PRINT_AREA:
2504 if ( bConvDueToOrientation || bFollowTextFlow )
2505 eHoriConv = CONV2PG;
2507 break;
2508 case text::RelOrientation::PAGE_LEFT:
2509 case text::RelOrientation::PAGE_RIGHT:
2511 // relation not supported by WW8. Thus, conversion always needed.
2512 eHoriConv = CONV2PG;
2514 break;
2515 case text::RelOrientation::FRAME:
2517 if ( bConvDueToOrientation )
2518 eHoriConv = CONV2COL;
2520 break;
2521 case text::RelOrientation::PRINT_AREA:
2522 case text::RelOrientation::FRAME_LEFT:
2523 case text::RelOrientation::FRAME_RIGHT:
2525 // relation not supported by WW8. Thus, conversion always needed.
2526 eHoriConv = CONV2COL;
2528 break;
2529 case text::RelOrientation::CHAR:
2531 if ( bConvDueToOrientation )
2532 eHoriConv = CONV2CHAR;
2534 break;
2535 default:
2536 OSL_FAIL( "<WinwordAnchoring::ConvertPosition(..)> - unknown horizontal relation" );
2539 if ( eHoriConv != NO_CONV )
2541 _iorHoriOri.SetHoriOrient( text::HoriOrientation::NONE );
2542 SwTwips nPosX( 0L );
2544 Point aPos;
2545 if ( eHoriConv == CONV2PG )
2547 _iorHoriOri.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
2548 // #i33818#
2549 bool bRelToTableCell( false );
2550 aPos = pAnchoredObj->GetRelPosToPageFrame( bFollowTextFlow,
2551 bRelToTableCell );
2552 if ( bRelToTableCell )
2554 _iorHoriOri.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA );
2557 else if ( eHoriConv == CONV2COL )
2559 _iorHoriOri.SetRelationOrient( text::RelOrientation::FRAME );
2560 aPos = pAnchoredObj->GetRelPosToAnchorFrame();
2562 else if ( eHoriConv == CONV2CHAR )
2564 _iorHoriOri.SetRelationOrient( text::RelOrientation::CHAR );
2565 aPos = pAnchoredObj->GetRelPosToChar();
2567 // No distinction between layout directions, because of missing
2568 // information about WW8 in vertical layout.
2569 nPosX = aPos.X();
2571 _iorHoriOri.SetPos( nPosX );
2572 bConverted = true;
2576 // convert vertical position, if needed
2578 enum VertConv { NO_CONV, CONV2PG, CONV2PARA, CONV2LINE };
2579 VertConv eVertConv( NO_CONV );
2581 // determine, if conversion has to be performed due to the position orientation
2582 bool bConvDueToOrientation( false );
2584 const sal_Int16 eVOri = _iorVertOri.GetVertOrient();
2585 bConvDueToOrientation = ( eVOri == text::VertOrientation::TOP ||
2586 eVOri == text::VertOrientation::BOTTOM ||
2587 eVOri == text::VertOrientation::CHAR_TOP ||
2588 eVOri == text::VertOrientation::CHAR_BOTTOM ||
2589 eVOri == text::VertOrientation::CHAR_CENTER ||
2590 eVOri == text::VertOrientation::LINE_TOP ||
2591 eVOri == text::VertOrientation::LINE_BOTTOM ||
2592 eVOri == text::VertOrientation::LINE_CENTER );
2595 // determine conversion type due to the position relation
2596 if ( bConvDueToAnchoredAtColBreakPara )
2598 eVertConv = CONV2PG;
2600 else
2602 switch ( _iorVertOri.GetRelationOrient() )
2604 case text::RelOrientation::PAGE_FRAME:
2605 case text::RelOrientation::PAGE_PRINT_AREA:
2607 if ( bConvDueToOrientation || bFollowTextFlow )
2608 eVertConv = CONV2PG;
2610 break;
2611 case text::RelOrientation::FRAME:
2613 if ( bConvDueToOrientation ||
2614 _iorVertOri.GetVertOrient() == text::VertOrientation::CENTER )
2616 eVertConv = CONV2PARA;
2619 break;
2620 case text::RelOrientation::PRINT_AREA:
2622 // relation not supported by WW8. Thus, conversion always needed.
2623 eVertConv = CONV2PARA;
2625 break;
2626 case text::RelOrientation::CHAR:
2628 // relation not supported by WW8. Thus, conversion always needed.
2629 eVertConv = CONV2PARA;
2631 break;
2632 case text::RelOrientation::TEXT_LINE:
2634 if ( bConvDueToOrientation ||
2635 _iorVertOri.GetVertOrient() == text::VertOrientation::NONE )
2637 eVertConv = CONV2LINE;
2640 break;
2641 case text::RelOrientation::PAGE_LEFT:
2642 case text::RelOrientation::PAGE_RIGHT:
2643 case text::RelOrientation::FRAME_LEFT:
2644 case text::RelOrientation::FRAME_RIGHT:
2645 default:
2646 OSL_FAIL( "<WinwordAnchoring::ConvertPosition(..)> - unknown vertical relation" );
2650 if ( eVertConv != NO_CONV )
2652 _iorVertOri.SetVertOrient( text::VertOrientation::NONE );
2653 SwTwips nPosY( 0L );
2655 Point aPos;
2656 if ( eVertConv == CONV2PG )
2658 _iorVertOri.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
2659 // #i33818#
2660 bool bRelToTableCell( false );
2661 aPos = pAnchoredObj->GetRelPosToPageFrame( bFollowTextFlow,
2662 bRelToTableCell );
2663 if ( bRelToTableCell )
2665 _iorVertOri.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA );
2668 else if ( eVertConv == CONV2PARA )
2670 _iorVertOri.SetRelationOrient( text::RelOrientation::FRAME );
2671 aPos = pAnchoredObj->GetRelPosToAnchorFrame();
2673 else if ( eVertConv == CONV2LINE )
2675 _iorVertOri.SetRelationOrient( text::RelOrientation::TEXT_LINE );
2676 aPos = pAnchoredObj->GetRelPosToLine();
2678 // No distinction between layout directions, because of missing
2679 // information about WW8 in vertical layout.
2680 nPosY = aPos.Y();
2682 _iorVertOri.SetPos( nPosY );
2683 bConverted = true;
2687 return bConverted;
2690 void WinwordAnchoring::SetAnchoring(const SwFrameFormat& rFormat)
2692 const RndStdIds eAnchor = rFormat.GetAnchor().GetAnchorId();
2693 mbInline = (eAnchor == FLY_AS_CHAR);
2695 SwFormatHoriOrient rHoriOri = rFormat.GetHoriOrient();
2696 SwFormatVertOrient rVertOri = rFormat.GetVertOrient();
2698 // #i30669# - convert the positioning attributes.
2699 // Most positions are converted, if layout information exists.
2700 const bool bPosConverted = ConvertPosition( rHoriOri, rVertOri, rFormat );
2702 const sal_Int16 eHOri = rHoriOri.GetHoriOrient();
2703 const sal_Int16 eVOri = rVertOri.GetVertOrient(); // #i22673#
2705 const sal_Int16 eHRel = rHoriOri.GetRelationOrient();
2706 const sal_Int16 eVRel = rVertOri.GetRelationOrient();
2708 // horizontal Adjustment
2709 switch (eHOri)
2711 default:
2712 case text::HoriOrientation::NONE:
2713 mnXAlign = 0;
2714 break;
2715 case text::HoriOrientation::LEFT:
2716 mnXAlign = 1;
2717 break;
2718 case text::HoriOrientation::CENTER:
2719 mnXAlign = 2;
2720 break;
2721 case text::HoriOrientation::RIGHT:
2722 mnXAlign = 3;
2723 break;
2724 case text::HoriOrientation::INSIDE:
2725 mnXAlign = 4;
2726 break;
2727 case text::HoriOrientation::OUTSIDE:
2728 mnXAlign = 5;
2729 break;
2732 // vertical Adjustment
2733 // #i22673#
2734 // When adjustment is vertically relative to line or to char
2735 // bottom becomes top and vice versa
2736 const bool bVertSwap = !bPosConverted &&
2737 ( (eVRel == text::RelOrientation::CHAR) ||
2738 (eVRel == text::RelOrientation::TEXT_LINE) );
2739 switch (eVOri)
2741 default:
2742 case text::VertOrientation::NONE:
2743 mnYAlign = 0;
2744 break;
2745 case text::VertOrientation::TOP:
2746 case text::VertOrientation::LINE_TOP:
2747 case text::VertOrientation::CHAR_TOP:
2748 mnYAlign = bVertSwap ? 3 : 1;
2749 break;
2750 case text::VertOrientation::CENTER:
2751 case text::VertOrientation::LINE_CENTER:
2752 mnYAlign = 2;
2753 break;
2754 case text::VertOrientation::BOTTOM:
2755 case text::VertOrientation::LINE_BOTTOM:
2756 case text::VertOrientation::CHAR_BOTTOM:
2757 mnYAlign = bVertSwap ? 1 : 3;
2758 break;
2761 // Adjustment is horizontally relative to...
2762 switch (eHRel)
2764 case text::RelOrientation::PAGE_PRINT_AREA:
2765 mnXRelTo = 0;
2766 break;
2767 case text::RelOrientation::PAGE_FRAME:
2768 case text::RelOrientation::PAGE_LEFT: //:-(
2769 case text::RelOrientation::PAGE_RIGHT: //:-(
2770 mnXRelTo = 1;
2771 break;
2772 case text::RelOrientation::FRAME:
2773 case text::RelOrientation::FRAME_LEFT: //:-(
2774 case text::RelOrientation::FRAME_RIGHT: //:-(
2775 if (eAnchor == FLY_AT_PAGE)
2776 mnXRelTo = 1;
2777 else
2778 mnXRelTo = 2;
2779 break;
2780 case text::RelOrientation::PRINT_AREA:
2781 if (eAnchor == FLY_AT_PAGE)
2782 mnXRelTo = 0;
2783 else
2784 mnXRelTo = 2;
2785 break;
2786 case text::RelOrientation::CHAR:
2787 mnXRelTo = 3;
2788 break;
2789 case text::RelOrientation::TEXT_LINE:
2790 break;
2793 // Adjustment is vertically relative to...
2794 switch (eVRel)
2796 case text::RelOrientation::PAGE_PRINT_AREA:
2797 mnYRelTo = 0;
2798 break;
2799 case text::RelOrientation::PAGE_FRAME:
2800 mnYRelTo = 1;
2801 break;
2802 case text::RelOrientation::PRINT_AREA:
2803 if (eAnchor == FLY_AT_PAGE)
2804 mnYRelTo = 0;
2805 else
2806 mnYRelTo = 2;
2807 break;
2808 case text::RelOrientation::FRAME:
2809 if (eAnchor == FLY_AT_PAGE)
2810 mnYRelTo = 1;
2811 else
2812 mnYRelTo = 2;
2813 break;
2814 case text::RelOrientation::CHAR:
2815 case text::RelOrientation::TEXT_LINE: // #i22673# - vertical alignment at top of line
2816 case text::RelOrientation::PAGE_LEFT: //nonsense
2817 case text::RelOrientation::PAGE_RIGHT: //nonsense
2818 case text::RelOrientation::FRAME_LEFT: //nonsense
2819 case text::RelOrientation::FRAME_RIGHT: //nonsense
2820 mnYRelTo = 3;
2821 break;
2825 void SwEscherEx::WriteFrameExtraData( const SwFrameFormat& rFormat )
2827 aWinwordAnchoring.SetAnchoring(rFormat);
2828 aWinwordAnchoring.WriteData(*this);
2830 AddAtom(4, ESCHER_ClientAnchor);
2831 GetStream().WriteInt32( 0 );
2833 AddAtom(4, ESCHER_ClientData);
2834 GetStream().WriteInt32( 1 );
2837 sal_Int32 SwEscherEx::WriteFlyFrame(const DrawObj &rObj, sal_uInt32 &rShapeId,
2838 DrawObjPointerVector &rPVec)
2840 const SwFrameFormat &rFormat = rObj.maContent.GetFrameFormat();
2842 // check for textflyframe and if it is the first in a Chain
2843 sal_Int32 nBorderThick = 0;
2844 const SwNodeIndex* pNdIdx = rFormat.GetContent().GetContentIdx();
2845 if( pNdIdx )
2847 SwNodeIndex aIdx( *pNdIdx, 1 );
2848 switch( aIdx.GetNode().GetNodeType() )
2850 case SwNodeType::Grf:
2851 nBorderThick = WriteGrfFlyFrame( rFormat, rShapeId = GenerateShapeId() );
2852 break;
2853 case SwNodeType::Ole:
2854 nBorderThick = WriteOLEFlyFrame( rFormat, rShapeId = GenerateShapeId() );
2855 break;
2856 default:
2857 if (const SdrObject* pObj = rFormat.FindRealSdrObject())
2859 // check for the first in a Chain
2860 sal_uInt32 nTextId;
2861 sal_uInt16 nOff = 0;
2862 const SwFrameFormat* pFormat = &rFormat, *pPrev;
2863 while( nullptr != ( pPrev = pFormat->GetChain().GetPrev() ))
2865 ++nOff;
2866 pFormat = pPrev;
2869 rShapeId = GetFlyShapeId(rFormat, rObj.mnHdFtIndex, rPVec);
2870 if( !nOff )
2872 nTextId = pTextBxs->GetPos( pObj );
2873 if( USHRT_MAX == nTextId )
2875 pTextBxs->Append( *pObj, rShapeId );
2876 nTextId = pTextBxs->Count();
2878 else
2879 ++nTextId;
2881 else
2883 const SdrObject* pPrevObj = pFormat->FindRealSdrObject();
2884 nTextId = pTextBxs->GetPos( pPrevObj );
2885 if( USHRT_MAX == nTextId )
2887 sal_uInt32 nPrevShapeId =
2888 GetFlyShapeId(*pFormat, rObj.mnHdFtIndex, rPVec);
2889 pTextBxs->Append( *pPrevObj, nPrevShapeId );
2890 nTextId = pTextBxs->Count();
2892 else
2893 ++nTextId;
2895 nTextId *= 0x10000;
2896 nTextId += nOff;
2898 nBorderThick = WriteTextFlyFrame(rObj, rShapeId, nTextId, rPVec);
2901 //In browse mode the sdr object doesn't always exist. For example, the
2902 //object is in the hidden header/footer. We save the fmt directly
2903 //in such cases; we copy most of the logic from the block above
2904 const bool bBrowseMode = rFormat.getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE);
2905 if( bBrowseMode && rFormat.GetDoc())
2907 if( !rFormat.GetChain().GetPrev() )//obj in header/footer?
2909 rShapeId = GetFlyShapeId(rFormat, rObj.mnHdFtIndex, rPVec);
2910 pTextBxs->Append( &rFormat, rShapeId );
2911 sal_uInt32 nTextId = pTextBxs->Count();
2913 nTextId *= 0x10000;
2914 nBorderThick = WriteTextFlyFrame(rObj, rShapeId, nTextId, rPVec);
2920 return nBorderThick;
2923 sal_uInt16 FindPos(const SwFrameFormat &rFormat, unsigned int nHdFtIndex,
2924 DrawObjPointerVector &rPVec)
2926 DrawObjPointerIter aEnd = rPVec.end();
2927 for (DrawObjPointerIter aIter = rPVec.begin(); aIter != aEnd; ++aIter)
2929 const DrawObj *pObj = (*aIter);
2930 OSL_ENSURE(pObj, "Impossible");
2931 if (!pObj)
2932 continue;
2933 if (
2934 nHdFtIndex == pObj->mnHdFtIndex &&
2935 &rFormat == (&pObj->maContent.GetFrameFormat())
2938 return static_cast< sal_uInt16 >(aIter - rPVec.begin());
2941 return USHRT_MAX;
2944 sal_Int32 SwEscherEx::WriteTextFlyFrame(const DrawObj &rObj, sal_uInt32 nShapeId,
2945 sal_uInt32 nTextBox, DrawObjPointerVector &rPVec)
2947 const SwFrameFormat &rFormat = rObj.maContent.GetFrameFormat();
2948 short nDirection = rObj.mnDirection;
2950 sal_Int32 nBorderThick=0;
2951 OpenContainer( ESCHER_SpContainer );
2953 AddShape( ESCHER_ShpInst_TextBox, 0xa00, nShapeId );
2954 EscherPropertyContainer aPropOpt;
2955 aPropOpt.AddOpt(ESCHER_Prop_lTxid, nTextBox);
2956 if (const SwFrameFormat *pNext = rFormat.GetChain().GetNext())
2958 sal_uInt16 nPos = FindPos(*pNext, rObj.mnHdFtIndex, rPVec);
2959 if (USHRT_MAX != nPos && aFollowShpIds[nPos])
2960 aPropOpt.AddOpt(ESCHER_Prop_hspNext, aFollowShpIds[nPos]);
2962 nBorderThick = WriteFlyFrameAttr( rFormat, mso_sptTextBox, aPropOpt );
2964 MSO_TextFlow nFlow;
2966 switch (nDirection)
2968 default:
2969 OSL_ENSURE(false, "unknown direction type");
2970 SAL_FALLTHROUGH;
2971 case FRMDIR_HORI_LEFT_TOP:
2972 nFlow=mso_txflHorzN;
2973 break;
2974 case FRMDIR_HORI_RIGHT_TOP:
2975 nFlow=mso_txflHorzN;
2976 break;
2977 case FRMDIR_VERT_TOP_LEFT: //not really possible in word
2978 case FRMDIR_VERT_TOP_RIGHT:
2979 nFlow=mso_txflTtoBA;
2980 break;
2982 aPropOpt.AddOpt( ESCHER_Prop_txflTextFlow, nFlow );
2984 aPropOpt.Commit( GetStream() );
2986 // store anchor attribute
2987 WriteFrameExtraData( rFormat );
2989 AddAtom( 4, ESCHER_ClientTextbox ); GetStream().WriteUInt32( nTextBox );
2991 CloseContainer(); // ESCHER_SpContainer
2992 return nBorderThick;
2995 void SwBasicEscherEx::WriteOLEPicture(EscherPropertyContainer &rPropOpt,
2996 sal_uInt32 nShapeFlags, const Graphic &rGraphic, const SdrObject &rObj,
2997 sal_uInt32 nShapeId, const awt::Rectangle* pVisArea )
2999 //nShapeFlags == 0xA00 + flips and ole active
3000 AddShape(ESCHER_ShpInst_PictureFrame, nShapeFlags, nShapeId);
3002 GraphicObject aGraphicObject(rGraphic);
3003 OString aId = aGraphicObject.GetUniqueID();
3004 if (!aId.isEmpty())
3006 Rectangle aRect = rObj.GetLogicRect();
3007 aRect.SetPos(Point(0,0));
3008 aRect.Right() = DrawModelToEmu(aRect.Right());
3009 aRect.Bottom() = DrawModelToEmu(aRect.Bottom());
3010 sal_uInt32 nBlibId = mxGlobal->GetBlibID( *QueryPictureStream(),
3011 aId, aRect, pVisArea); // SJ: the fourth parameter (VisArea) should be set..
3012 if (nBlibId)
3013 rPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, true);
3016 SetPicId(rObj, nShapeId, rPropOpt);
3017 rPropOpt.AddOpt( ESCHER_Prop_pictureActive, 0x10000 );
3020 void SwEscherEx::WriteOCXControl( const SwFrameFormat& rFormat, sal_uInt32 nShapeId )
3022 if (const SdrObject* pSdrObj = rFormat.FindRealSdrObject())
3024 OpenContainer( ESCHER_SpContainer );
3026 SwDrawModel *pModel = rWrt.m_pDoc->getIDocumentDrawModelAccess().GetDrawModel();
3027 OutputDevice *pDevice = Application::GetDefaultDevice();
3028 OSL_ENSURE(pModel && pDevice, "no model or device");
3030 // #i71538# use complete SdrViews
3031 // SdrExchangeView aExchange(pModel, pDevice);
3032 SdrView aExchange(pModel, pDevice);
3034 Graphic aGraphic(SdrExchangeView::GetObjGraphic(pModel, pSdrObj));
3036 EscherPropertyContainer aPropOpt;
3037 WriteOLEPicture(aPropOpt, 0xa00 | SHAPEFLAG_OLESHAPE, aGraphic,
3038 *pSdrObj, nShapeId, nullptr );
3040 WriteFlyFrameAttr( rFormat, mso_sptPictureFrame , aPropOpt );
3041 aPropOpt.Commit( GetStream() );
3043 // store anchor attribute
3044 WriteFrameExtraData( rFormat );
3046 CloseContainer(); // ESCHER_SpContainer
3050 void SwEscherEx::MakeZOrderArrAndFollowIds(
3051 std::vector<DrawObj>& rSrcArr, std::vector<DrawObj*>&rDstArr)
3053 ::lcl_makeZOrderArray(rWrt, rSrcArr, rDstArr);
3055 //Now set up the follow IDs
3056 aFollowShpIds.clear();
3058 for (DrawObj* p : rDstArr)
3060 const SwFrameFormat &rFormat = p->maContent.GetFrameFormat();
3061 bool bNeedsShapeId = false;
3063 if (RES_FLYFRMFMT == rFormat.Which())
3065 const SwFormatChain &rChain = rFormat.GetChain();
3066 if (rChain.GetPrev() || rChain.GetNext())
3067 bNeedsShapeId = true;
3070 sal_uLong nShapeId = bNeedsShapeId ? GenerateShapeId() : 0;
3072 aFollowShpIds.push_back(nShapeId);
3076 sal_uInt32 SwEscherEx::GetFlyShapeId(const SwFrameFormat& rFormat,
3077 unsigned int nHdFtIndex, DrawObjPointerVector &rpVec)
3079 sal_uInt16 nPos = FindPos(rFormat, nHdFtIndex, rpVec);
3080 sal_uInt32 nShapeId;
3081 if (USHRT_MAX != nPos)
3083 if (0 == (nShapeId = aFollowShpIds[nPos]))
3085 nShapeId = GenerateShapeId();
3086 aFollowShpIds[ nPos ] = nShapeId;
3089 else
3090 nShapeId = GenerateShapeId();
3091 return nShapeId;
3094 sal_uInt32 SwEscherEx::QueryTextID(
3095 const uno::Reference< drawing::XShape>& xXShapeRef, sal_uInt32 nShapeId )
3097 sal_uInt32 nId = 0;
3098 if (SdrObject* pObj = GetSdrObjectFromXShape(xXShapeRef))
3100 pTextBxs->Append( *pObj, nShapeId );
3101 nId = pTextBxs->Count();
3102 nId *= 0x10000;
3104 return nId;
3107 SwMSConvertControls::SwMSConvertControls( SfxObjectShell *pDSh,SwPaM *pP ) : oox
3108 ::ole::MSConvertOCXControls( pDSh ? pDSh->GetModel() : nullptr ), pPaM( pP ), mnObjectId(0)
3113 // in transitioning away old filter for ole/ocx controls, ReadOCXStream has been made pure virtual in
3114 // filter/source/msocximex.cxx, so.. we need an implementation here
3115 bool SwMSConvertControls::ReadOCXStream( tools::SvRef<SotStorage>& rSrc1,
3116 css::uno::Reference< css::drawing::XShape > *pShapeRef,
3117 bool bFloatingCtrl )
3119 uno::Reference< form::XFormComponent > xFComp;
3120 bool bRes = oox::ole::MSConvertOCXControls::ReadOCXStorage( rSrc1, xFComp );
3121 if ( bRes && xFComp.is() )
3123 css::awt::Size aSz; // not used in import
3124 bRes = InsertControl( xFComp, aSz,pShapeRef,bFloatingCtrl);
3126 return bRes;
3129 void SwMSConvertControls::ExportControl(WW8Export &rWW8Wrt, const SdrUnoObj& rFormObj)
3131 const uno::Reference< awt::XControlModel >& xControlModel =
3132 rFormObj.GetUnoControlModel();
3134 //Why oh lord do we use so many different units ?
3135 //I think I painted myself into a little bit of a
3136 //corner by trying to use the uno interface for
3137 //controls export
3138 Rectangle aRect = rFormObj.GetLogicRect();
3139 aRect.SetPos(Point(0,0));
3140 awt::Size aSize;
3141 aSize.Width = TWIPS_TO_MM(aRect.Right());
3142 aSize.Height = TWIPS_TO_MM(aRect.Bottom());
3144 //Open the ObjectPool
3145 tools::SvRef<SotStorage> xObjPool = rWW8Wrt.GetWriter().GetStorage().OpenSotStorage(
3146 OUString(SL::aObjectPool));
3148 //Create a destination storage for the microsoft control
3149 OUStringBuffer sStorageName;
3150 sal_uInt32 nObjId = ++mnObjectId;
3151 sStorageName.append('_').append( static_cast<sal_Int64>( nObjId ));
3152 tools::SvRef<SotStorage> xOleStg = xObjPool->OpenSotStorage(sStorageName.makeStringAndClear());
3154 if (!xOleStg.Is())
3155 return;
3157 OUString sUName;
3158 if (!WriteOCXStream( mxModel, xOleStg,xControlModel,aSize,sUName))
3159 return;
3161 sal_uInt8 aSpecOLE[] =
3163 0x03, 0x6a, 0xFF, 0xFF, 0xFF, 0xFF, // sprmCPicLocation
3164 0x0a, 0x08, 1, // sprmCFOLE2
3165 0x55, 0x08, 1, // sprmCFSpec
3166 0x56, 0x08, 1 // sprmCFObj
3168 //Set the obj id into the sprmCPicLocation
3169 sal_uInt8 *pData = aSpecOLE+2;
3170 Set_UInt32(pData,nObjId );
3172 OUString sField = FieldString(ww::eCONTROL) + "Forms." + sUName + ".1 \\s ";
3174 rWW8Wrt.OutputField(nullptr, ww::eCONTROL, sField,
3175 WRITEFIELD_START|WRITEFIELD_CMD_START|WRITEFIELD_CMD_END);
3177 rWW8Wrt.m_pChpPlc->AppendFkpEntry(rWW8Wrt.Strm().Tell(),sizeof(aSpecOLE),
3178 aSpecOLE);
3179 rWW8Wrt.WriteChar( 0x1 );
3180 rWW8Wrt.OutputField(nullptr, ww::eCONTROL, OUString(), WRITEFIELD_END | WRITEFIELD_CLOSE);
3183 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */