LibreOffice Module sw (master)  1
docxsdrexport.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  */
9 
10 #include "docxsdrexport.hxx"
11 #include <com/sun/star/beans/XPropertySet.hpp>
12 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
13 #include <editeng/lrspitem.hxx>
14 #include <editeng/ulspitem.hxx>
15 #include <editeng/shaditem.hxx>
16 #include <editeng/opaqitem.hxx>
17 #include <editeng/boxitem.hxx>
18 #include <svx/svdogrp.hxx>
19 #include <oox/token/namespaces.hxx>
20 #include <textboxhelper.hxx>
21 #include <fmtanchr.hxx>
22 #include <fmtsrnd.hxx>
23 #include <fmtcntnt.hxx>
24 #include <fmtornt.hxx>
25 #include <fmtfsize.hxx>
26 #include <frmatr.hxx>
28 #include "docxattributeoutput.hxx"
29 #include "docxexportfilter.hxx"
30 #include <comphelper/flagguard.hxx>
31 #include <comphelper/sequence.hxx>
33 #include <sal/log.hxx>
34 #include <frmfmt.hxx>
36 
37 using namespace com::sun::star;
38 using namespace oox;
39 
40 namespace
41 {
42 uno::Sequence<beans::PropertyValue> lclGetProperty(const uno::Reference<drawing::XShape>& rShape,
43  const OUString& rPropName)
44 {
45  uno::Sequence<beans::PropertyValue> aResult;
46  uno::Reference<beans::XPropertySet> xPropertySet(rShape, uno::UNO_QUERY);
47  uno::Reference<beans::XPropertySetInfo> xPropSetInfo;
48 
49  if (!xPropertySet.is())
50  return aResult;
51 
52  xPropSetInfo = xPropertySet->getPropertySetInfo();
53  if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(rPropName))
54  {
55  xPropertySet->getPropertyValue(rPropName) >>= aResult;
56  }
57  return aResult;
58 }
59 
60 OUString lclGetAnchorIdFromGrabBag(const SdrObject* pObj)
61 {
62  OUString aResult;
63  uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pObj)->getUnoShape(),
64  uno::UNO_QUERY);
65  OUString aGrabBagName;
66  uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY);
67  if (xServiceInfo->supportsService("com.sun.star.text.TextFrame"))
68  aGrabBagName = "FrameInteropGrabBag";
69  else
70  aGrabBagName = "InteropGrabBag";
71  uno::Sequence<beans::PropertyValue> propList = lclGetProperty(xShape, aGrabBagName);
72  auto pProp
73  = std::find_if(propList.begin(), propList.end(),
74  [](const beans::PropertyValue& rProp) { return rProp.Name == "AnchorId"; });
75  if (pProp != propList.end())
76  pProp->Value >>= aResult;
77  return aResult;
78 }
79 
80 void lclMovePositionWithRotation(awt::Point& aPos, const Size& rSize, Degree100 nRotation100)
81 {
82  // code from ImplEESdrWriter::ImplFlipBoundingBox (filter/source/msfilter/eschesdo.cxx)
83  // TODO: refactor
84 
85  if (nRotation100 == 0_deg100)
86  return;
87  sal_Int64 nRotation = nRotation100.get();
88  if (nRotation < 0)
89  nRotation = (36000 + nRotation) % 36000;
90  if (nRotation % 18000 == 0)
91  nRotation = 0;
92  while (nRotation > 9000)
93  nRotation = (18000 - (nRotation % 18000));
94 
95  double fVal = static_cast<double>(nRotation) * F_PI18000;
96  double fCos = cos(fVal);
97  double fSin = sin(fVal);
98 
99  double nWidthHalf = static_cast<double>(rSize.Width()) / 2;
100  double nHeightHalf = static_cast<double>(rSize.Height()) / 2;
101 
102  double nXDiff = fSin * nHeightHalf + fCos * nWidthHalf - nWidthHalf;
103  double nYDiff = fSin * nWidthHalf + fCos * nHeightHalf - nHeightHalf;
104 
105  aPos.X += nXDiff;
106  aPos.Y += nYDiff;
107 }
108 
110 bool IsAnchorTypeInsideParagraph(const ww8::Frame* pFrame)
111 {
112  const SwFormatAnchor& rAnchor = pFrame->GetFrameFormat().GetAttrSet().GetAnchor();
113  return rAnchor.GetAnchorId() != RndStdIds::FLY_AT_PAGE;
114 }
115 }
116 
118  ww8::Frame const* pParentFrame)
119  : m_rExport(rExport)
120 {
121  m_rExport.SaveData(nStt, nEnd);
122  m_rExport.m_pParentFrame = pParentFrame;
123 }
124 
126 
129 {
130 private:
139  OStringBuffer m_aTextFrameStyle;
151 
152 public:
153  bool m_bFlyFrameGraphic = false;
154 
156  oox::drawingml::DrawingML* pDrawingML)
157  : m_rExport(rExport)
158  , m_pSerializer(std::move(pSerializer))
159  , m_pDrawingML(pDrawingML)
160  , m_pFlyFrameSize(nullptr)
161  , m_bTextFrameSyntax(false)
162  , m_bDMLTextFrameSyntax(false)
163  , m_bDrawingOpen(false)
164  , m_bParagraphSdtOpen(false)
165  , m_bParagraphHasDrawing(false)
166  , m_pFlyWrapAttrList(nullptr)
167  , m_pBodyPrAttrList(nullptr)
168  , m_bDMLAndVMLDrawingOpen(false)
169  {
170  }
171 
173 
174  void textFrameShadow(const SwFrameFormat& rFrameFormat);
175  static bool isSupportedDMLShape(const uno::Reference<drawing::XShape>& xShape);
176 
178  {
179  m_pSerializer = pSerializer;
180  }
181 
183 
184  void setFlyFrameSize(const Size* pFlyFrameSize) { m_pFlyFrameSize = pFlyFrameSize; }
185 
186  const Size* getFlyFrameSize() const { return m_pFlyFrameSize; }
187 
188  void setTextFrameSyntax(bool bTextFrameSyntax) { m_bTextFrameSyntax = bTextFrameSyntax; }
189 
190  bool getTextFrameSyntax() const { return m_bTextFrameSyntax; }
191 
192  void setDMLTextFrameSyntax(bool bDMLTextFrameSyntax)
193  {
194  m_bDMLTextFrameSyntax = bDMLTextFrameSyntax;
195  }
196 
198 
200  {
201  m_pFlyAttrList = pFlyAttrList;
202  }
203 
205 
206  void
208  {
209  m_pTextboxAttrList = pTextboxAttrList;
210  }
211 
213  {
214  return m_pTextboxAttrList;
215  }
216 
217  OStringBuffer& getTextFrameStyle() { return m_aTextFrameStyle; }
218 
219  void setDrawingOpen(bool bDrawingOpen) { m_bDrawingOpen = bDrawingOpen; }
220 
221  bool getDrawingOpen() const { return m_bDrawingOpen; }
222 
223  void setParagraphSdtOpen(bool bParagraphSdtOpen) { m_bParagraphSdtOpen = bParagraphSdtOpen; }
224 
225  bool getParagraphSdtOpen() const { return m_bParagraphSdtOpen; }
226 
227  void setDMLAndVMLDrawingOpen(bool bDMLAndVMLDrawingOpen)
228  {
229  m_bDMLAndVMLDrawingOpen = bDMLAndVMLDrawingOpen;
230  }
231 
233 
234  void setParagraphHasDrawing(bool bParagraphHasDrawing)
235  {
236  m_bParagraphHasDrawing = bParagraphHasDrawing;
237  }
238 
240 
242  {
243  return m_pFlyFillAttrList;
244  }
245 
247  {
248  m_pFlyWrapAttrList = pFlyWrapAttrList;
249  }
250 
252 
254  {
255  m_pBodyPrAttrList = pBodyPrAttrList;
256  }
257 
259 
261  {
262  return m_pDashLineStyleAttr;
263  }
264 
265  bool getFlyFrameGraphic() const { return m_bFlyFrameGraphic; }
266 
268 
269  DocxExport& getExport() const { return m_rExport; }
270 
271  void setDMLandVMLTextFrameRotation(Degree100 nDMLandVMLTextFrameRotation)
272  {
273  m_nDMLandVMLTextFrameRotation = nDMLandVMLTextFrameRotation;
274  }
275 
277 };
278 
280  oox::drawingml::DrawingML* pDrawingML)
281  : m_pImpl(std::make_unique<Impl>(rExport, pSerializer, pDrawingML))
282 {
283 }
284 
286 
288 {
289  m_pImpl->setSerializer(pSerializer);
290 }
291 
292 const Size* DocxSdrExport::getFlyFrameSize() const { return m_pImpl->getFlyFrameSize(); }
293 
294 bool DocxSdrExport::getTextFrameSyntax() const { return m_pImpl->getTextFrameSyntax(); }
295 
296 bool DocxSdrExport::getDMLTextFrameSyntax() const { return m_pImpl->getDMLTextFrameSyntax(); }
297 
299 {
300  return m_pImpl->getFlyAttrList();
301 }
302 
304 {
305  return m_pImpl->getTextboxAttrList();
306 }
307 
308 OStringBuffer& DocxSdrExport::getTextFrameStyle() { return m_pImpl->getTextFrameStyle(); }
309 
310 bool DocxSdrExport::IsDrawingOpen() const { return m_pImpl->getDrawingOpen(); }
311 
312 void DocxSdrExport::setParagraphSdtOpen(bool bParagraphSdtOpen)
313 {
314  m_pImpl->setParagraphSdtOpen(bParagraphSdtOpen);
315 }
316 
317 bool DocxSdrExport::IsDMLAndVMLDrawingOpen() const { return m_pImpl->getDMLAndVMLDrawingOpen(); }
318 
319 bool DocxSdrExport::IsParagraphHasDrawing() const { return m_pImpl->getParagraphHasDrawing(); }
320 
321 void DocxSdrExport::setParagraphHasDrawing(bool bParagraphHasDrawing)
322 {
323  m_pImpl->setParagraphHasDrawing(bParagraphHasDrawing);
324 }
325 
327 {
328  return m_pImpl->getFlyFillAttrList();
329 }
330 
332 {
333  return m_pImpl->getBodyPrAttrList();
334 }
335 
337 {
338  return m_pImpl->getDashLineStyleAttr();
339 }
340 
342 {
343  m_pImpl->setFlyWrapAttrList(pAttrList);
344 }
345 
346 void DocxSdrExport::startDMLAnchorInline(const SwFrameFormat* pFrameFormat, const Size& rSize)
347 {
348  m_pImpl->setDrawingOpen(true);
349  m_pImpl->setParagraphHasDrawing(true);
350  m_pImpl->getSerializer()->startElementNS(XML_w, XML_drawing);
351 
352  // tdf#135047: It must be allowed to find in parents too, but default value of bInP parameter
353  // for GetLRSpace() and GetULSpace() is true, so no direct setting is required.
354  const SvxLRSpaceItem& aLRSpaceItem = pFrameFormat->GetLRSpace();
355  const SvxULSpaceItem& aULSpaceItem = pFrameFormat->GetULSpace();
356 
357  bool isAnchor;
358 
359  if (m_pImpl->getFlyFrameGraphic())
360  {
361  isAnchor = false; // make Graphic object inside DMLTextFrame & VMLTextFrame as Inline
362  }
363  else
364  {
365  isAnchor = pFrameFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR;
366  }
367 
368  // Count effectExtent values, their value is needed before dist{T,B,L,R} is written.
369  SvxShadowItem aShadowItem = pFrameFormat->GetShadow();
370  sal_Int32 nLeftExt = 0;
371  sal_Int32 nRightExt = 0;
372  sal_Int32 nTopExt = 0;
373  sal_Int32 nBottomExt = 0;
374  if (aShadowItem.GetLocation() != SvxShadowLocation::NONE)
375  {
376  sal_Int32 nShadowWidth(TwipsToEMU(aShadowItem.GetWidth()));
377  switch (aShadowItem.GetLocation())
378  {
379  case SvxShadowLocation::TopLeft:
380  nTopExt = nLeftExt = nShadowWidth;
381  break;
382  case SvxShadowLocation::TopRight:
383  nTopExt = nRightExt = nShadowWidth;
384  break;
385  case SvxShadowLocation::BottomLeft:
386  nBottomExt = nLeftExt = nShadowWidth;
387  break;
388  case SvxShadowLocation::BottomRight:
389  nBottomExt = nRightExt = nShadowWidth;
390  break;
391  case SvxShadowLocation::NONE:
392  case SvxShadowLocation::End:
393  break;
394  }
395  }
396  else if (const SdrObject* pObject = pFrameFormat->FindRealSdrObject())
397  {
398  // No shadow, but we have an idea what was the original effectExtent.
399  uno::Any aAny;
400  pObject->GetGrabBagItem(aAny);
401  comphelper::SequenceAsHashMap aGrabBag(aAny);
402  auto it = aGrabBag.find("CT_EffectExtent");
403  if (it != aGrabBag.end())
404  {
405  comphelper::SequenceAsHashMap aEffectExtent(it->second);
406  for (const std::pair<const OUString, uno::Any>& rDirection : aEffectExtent)
407  {
408  if (rDirection.first == "l" && rDirection.second.has<sal_Int32>())
409  nLeftExt = rDirection.second.get<sal_Int32>();
410  else if (rDirection.first == "t" && rDirection.second.has<sal_Int32>())
411  nTopExt = rDirection.second.get<sal_Int32>();
412  else if (rDirection.first == "r" && rDirection.second.has<sal_Int32>())
413  nRightExt = rDirection.second.get<sal_Int32>();
414  else if (rDirection.first == "b" && rDirection.second.has<sal_Int32>())
415  nBottomExt = rDirection.second.get<sal_Int32>();
416  }
417  }
418  }
419 
420  if (isAnchor)
421  {
424  bool bOpaque = pFrameFormat->GetOpaque().GetValue();
425  awt::Point aPos(pFrameFormat->GetHoriOrient().GetPos(),
426  pFrameFormat->GetVertOrient().GetPos());
427  const SdrObject* pObj = pFrameFormat->FindRealSdrObject();
428  Degree100 nRotation(0);
429  if (pObj != nullptr)
430  {
431  // SdrObjects know their layer, consider that instead of the frame format.
432  bOpaque = pObj->GetLayer()
433  != pFrameFormat->GetDoc()->getIDocumentDrawModelAccess().GetHellId()
434  && pObj->GetLayer()
435  != pFrameFormat->GetDoc()
438 
439  // Do not do this with lines.
440  if (pObj->GetObjIdentifier() != OBJ_LINE)
441  {
442  nRotation = pObj->GetRotateAngle();
443  lclMovePositionWithRotation(aPos, rSize, nRotation);
444  }
445  }
446  attrList->add(XML_behindDoc, bOpaque ? "0" : "1");
447  // Extend distance with the effect extent if the shape is not rotated, which is the opposite
448  // of the mapping done at import time.
449  // The type of dist* attributes is unsigned, so make sure no negative value is written.
450  sal_Int64 nTopExtDist = nRotation ? 0 : nTopExt;
451  sal_Int64 nDistT = std::max(static_cast<sal_Int64>(0),
452  TwipsToEMU(aULSpaceItem.GetUpper()) - nTopExtDist);
453  attrList->add(XML_distT, OString::number(nDistT).getStr());
454  sal_Int64 nBottomExtDist = nRotation ? 0 : nBottomExt;
455  sal_Int64 nDistB = std::max(static_cast<sal_Int64>(0),
456  TwipsToEMU(aULSpaceItem.GetLower()) - nBottomExtDist);
457  attrList->add(XML_distB, OString::number(nDistB).getStr());
458  sal_Int64 nLeftExtDist = nRotation ? 0 : nLeftExt;
459  sal_Int64 nDistL = std::max(static_cast<sal_Int64>(0),
460  TwipsToEMU(aLRSpaceItem.GetLeft()) - nLeftExtDist);
461  attrList->add(XML_distL, OString::number(nDistL).getStr());
462  sal_Int64 nRightExtDist = nRotation ? 0 : nRightExt;
463  sal_Int64 nDistR = std::max(static_cast<sal_Int64>(0),
464  TwipsToEMU(aLRSpaceItem.GetRight()) - nRightExtDist);
465  attrList->add(XML_distR, OString::number(nDistR).getStr());
466  attrList->add(XML_simplePos, "0");
467  attrList->add(XML_locked, "0");
468  bool bLclInTabCell = true;
469  if (pObj)
470  {
471  uno::Reference<drawing::XShape> xShape((const_cast<SdrObject*>(pObj)->getUnoShape()),
472  uno::UNO_QUERY);
473  uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
474  if (xShapeProps.is())
475  xShapeProps->getPropertyValue("IsFollowingTextFlow") >>= bLclInTabCell;
476  }
477  if (bLclInTabCell)
478  attrList->add(XML_layoutInCell, "1");
479  else
480  attrList->add(XML_layoutInCell, "0");
481  bool bAllowOverlap = pFrameFormat->GetWrapInfluenceOnObjPos().GetAllowOverlap();
482  attrList->add(XML_allowOverlap, bAllowOverlap ? "1" : "0");
483  if (pObj != nullptr)
484  // It seems 0 and 1 have special meaning: just start counting from 2 to avoid issues with that.
485  attrList->add(XML_relativeHeight, OString::number(pObj->GetOrdNum() + 2));
486  else
487  // relativeHeight is mandatory attribute, if value is not present, we must write default value
488  attrList->add(XML_relativeHeight, "0");
489  if (pObj != nullptr)
490  {
491  OUString sAnchorId = lclGetAnchorIdFromGrabBag(pObj);
492  if (!sAnchorId.isEmpty())
493  attrList->addNS(XML_wp14, XML_anchorId,
494  OUStringToOString(sAnchorId, RTL_TEXTENCODING_UTF8));
495  }
496  sax_fastparser::XFastAttributeListRef xAttrList(attrList);
497  m_pImpl->getSerializer()->startElementNS(XML_wp, XML_anchor, xAttrList);
498  m_pImpl->getSerializer()->singleElementNS(XML_wp, XML_simplePos, XML_x, "0", XML_y,
499  "0"); // required, unused
500  const char* relativeFromH;
501  const char* relativeFromV;
502  const char* alignH = nullptr;
503  const char* alignV = nullptr;
504  switch (pFrameFormat->GetVertOrient().GetRelationOrient())
505  {
506  case text::RelOrientation::PAGE_PRINT_AREA:
507  relativeFromV = "margin";
508  break;
509  case text::RelOrientation::PAGE_PRINT_AREA_TOP:
510  relativeFromV = "topMargin";
511  break;
512  case text::RelOrientation::PAGE_PRINT_AREA_BOTTOM:
513  relativeFromV = "bottomMargin";
514  break;
515  case text::RelOrientation::PAGE_FRAME:
516  relativeFromV = "page";
517  break;
518  case text::RelOrientation::FRAME:
519  relativeFromV = "paragraph";
520  break;
521  case text::RelOrientation::TEXT_LINE:
522  default:
523  relativeFromV = "line";
524  break;
525  }
526  switch (pFrameFormat->GetVertOrient().GetVertOrient())
527  {
528  case text::VertOrientation::TOP:
529  case text::VertOrientation::CHAR_TOP:
530  case text::VertOrientation::LINE_TOP:
531  if (pFrameFormat->GetVertOrient().GetRelationOrient()
532  == text::RelOrientation::TEXT_LINE)
533  alignV = "bottom";
534  else
535  alignV = "top";
536  break;
537  case text::VertOrientation::BOTTOM:
538  case text::VertOrientation::CHAR_BOTTOM:
539  case text::VertOrientation::LINE_BOTTOM:
540  if (pFrameFormat->GetVertOrient().GetRelationOrient()
541  == text::RelOrientation::TEXT_LINE)
542  alignV = "top";
543  else
544  alignV = "bottom";
545  break;
546  case text::VertOrientation::CENTER:
547  case text::VertOrientation::CHAR_CENTER:
548  case text::VertOrientation::LINE_CENTER:
549  alignV = "center";
550  break;
551  default:
552  break;
553  }
554  switch (pFrameFormat->GetHoriOrient().GetRelationOrient())
555  {
556  case text::RelOrientation::PAGE_PRINT_AREA:
557  relativeFromH = "margin";
558  break;
559  case text::RelOrientation::PAGE_FRAME:
560  relativeFromH = "page";
561  break;
562  case text::RelOrientation::CHAR:
563  relativeFromH = "character";
564  break;
565  case text::RelOrientation::PAGE_RIGHT:
566  relativeFromH = "rightMargin";
567  break;
568  case text::RelOrientation::PAGE_LEFT:
569  relativeFromH = "leftMargin";
570  break;
571  case text::RelOrientation::FRAME:
572  default:
573  relativeFromH = "column";
574  break;
575  }
576  switch (pFrameFormat->GetHoriOrient().GetHoriOrient())
577  {
578  case text::HoriOrientation::LEFT:
579  alignH = "left";
580  break;
581  case text::HoriOrientation::RIGHT:
582  alignH = "right";
583  break;
584  case text::HoriOrientation::CENTER:
585  alignH = "center";
586  break;
587  case text::HoriOrientation::INSIDE:
588  alignH = "inside";
589  break;
590  case text::HoriOrientation::OUTSIDE:
591  alignH = "outside";
592  break;
593  default:
594  break;
595  }
596  m_pImpl->getSerializer()->startElementNS(XML_wp, XML_positionH, XML_relativeFrom,
597  relativeFromH);
603  const sal_Int64 MAX_INTEGER_VALUE = SAL_MAX_INT32;
604  const sal_Int64 MIN_INTEGER_VALUE = SAL_MIN_INT32;
605  if (alignH != nullptr)
606  {
607  m_pImpl->getSerializer()->startElementNS(XML_wp, XML_align);
608  m_pImpl->getSerializer()->write(alignH);
609  m_pImpl->getSerializer()->endElementNS(XML_wp, XML_align);
610  }
611  else
612  {
613  m_pImpl->getSerializer()->startElementNS(XML_wp, XML_posOffset);
614  sal_Int64 nPosXEMU = TwipsToEMU(aPos.X);
615 
616  /* Absolute Position Offset Value is of type Int. Hence it should not be greater than
617  * Maximum value for Int OR Less than the Minimum value for Int.
618  * - Maximum value for Int = 2147483647
619  * - Minimum value for Int = -2147483648
620  *
621  * As per ECMA Specification : ECMA-376, Second Edition,
622  * Part 1 - Fundamentals And Markup Language Reference[20.4.3.3 ST_PositionOffset (Absolute Position Offset Value)]
623  *
624  * Please refer : http://www.schemacentral.com/sc/xsd/t-xsd_int.html
625  */
626 
627  if (nPosXEMU > MAX_INTEGER_VALUE)
628  {
629  nPosXEMU = MAX_INTEGER_VALUE;
630  }
631  else if (nPosXEMU < MIN_INTEGER_VALUE)
632  {
633  nPosXEMU = MIN_INTEGER_VALUE;
634  }
635  m_pImpl->getSerializer()->write(nPosXEMU);
636  m_pImpl->getSerializer()->endElementNS(XML_wp, XML_posOffset);
637  }
638  m_pImpl->getSerializer()->endElementNS(XML_wp, XML_positionH);
639  m_pImpl->getSerializer()->startElementNS(XML_wp, XML_positionV, XML_relativeFrom,
640  relativeFromV);
641 
642  sal_Int64 nPosYEMU = TwipsToEMU(aPos.Y);
643 
644  // tdf#93675, 0 below line/paragraph and/or top line/paragraph with
645  // wrap top+bottom or other wraps is affecting the line directly
646  // above the anchor line, which seems odd, but a tiny adjustment
647  // here to bring the top down convinces msoffice to wrap like us
648  if (nPosYEMU == 0
649  && (strcmp(relativeFromV, "line") == 0 || strcmp(relativeFromV, "paragraph") == 0)
650  && (!alignV || strcmp(alignV, "top") == 0))
651  {
652  alignV = nullptr;
653  nPosYEMU = 635;
654  }
655 
656  if (alignV != nullptr)
657  {
658  m_pImpl->getSerializer()->startElementNS(XML_wp, XML_align);
659  m_pImpl->getSerializer()->write(alignV);
660  m_pImpl->getSerializer()->endElementNS(XML_wp, XML_align);
661  }
662  else
663  {
664  m_pImpl->getSerializer()->startElementNS(XML_wp, XML_posOffset);
665  if (nPosYEMU > MAX_INTEGER_VALUE)
666  {
667  nPosYEMU = MAX_INTEGER_VALUE;
668  }
669  else if (nPosYEMU < MIN_INTEGER_VALUE)
670  {
671  nPosYEMU = MIN_INTEGER_VALUE;
672  }
673  m_pImpl->getSerializer()->write(nPosYEMU);
674  m_pImpl->getSerializer()->endElementNS(XML_wp, XML_posOffset);
675  }
676  m_pImpl->getSerializer()->endElementNS(XML_wp, XML_positionV);
677  }
678  else
679  {
682  aAttrList->add(XML_distT, OString::number(TwipsToEMU(aULSpaceItem.GetUpper())).getStr());
683  aAttrList->add(XML_distB, OString::number(TwipsToEMU(aULSpaceItem.GetLower())).getStr());
684  aAttrList->add(XML_distL, OString::number(TwipsToEMU(aLRSpaceItem.GetLeft())).getStr());
685  aAttrList->add(XML_distR, OString::number(TwipsToEMU(aLRSpaceItem.GetRight())).getStr());
686  const SdrObject* pObj = pFrameFormat->FindRealSdrObject();
687  if (pObj != nullptr)
688  {
689  OUString sAnchorId = lclGetAnchorIdFromGrabBag(pObj);
690  if (!sAnchorId.isEmpty())
691  aAttrList->addNS(XML_wp14, XML_anchorId,
692  OUStringToOString(sAnchorId, RTL_TEXTENCODING_UTF8));
693  }
694  m_pImpl->getSerializer()->startElementNS(XML_wp, XML_inline, aAttrList);
695  }
696 
697  // now the common parts
698  // extent of the image
716  sal_uInt64 cx
717  = TwipsToEMU(std::clamp(rSize.Width(), tools::Long(0), tools::Long(SAL_MAX_INT32)));
718  OString aWidth(OString::number(std::min(cx, sal_uInt64(SAL_MAX_INT32))));
719  sal_uInt64 cy
720  = TwipsToEMU(std::clamp(rSize.Height(), tools::Long(0), tools::Long(SAL_MAX_INT32)));
721  OString aHeight(OString::number(std::min(cy, sal_uInt64(SAL_MAX_INT32))));
722 
723  m_pImpl->getSerializer()->singleElementNS(XML_wp, XML_extent, XML_cx, aWidth, XML_cy, aHeight);
724 
725  // effectExtent, extent including the effect (shadow only for now)
726  m_pImpl->getSerializer()->singleElementNS(
727  XML_wp, XML_effectExtent, XML_l, OString::number(nLeftExt), XML_t, OString::number(nTopExt),
728  XML_r, OString::number(nRightExt), XML_b, OString::number(nBottomExt));
729 
730  // See if we know the exact wrap type from grab-bag.
731  sal_Int32 nWrapToken = 0;
732  if (const SdrObject* pObject = pFrameFormat->FindRealSdrObject())
733  {
734  uno::Any aAny;
735  pObject->GetGrabBagItem(aAny);
736  comphelper::SequenceAsHashMap aGrabBag(aAny);
737  auto it = aGrabBag.find("EG_WrapType");
738  if (it != aGrabBag.end())
739  {
740  auto sType = it->second.get<OUString>();
741  if (sType == "wrapTight")
742  nWrapToken = XML_wrapTight;
743  else if (sType == "wrapThrough")
744  nWrapToken = XML_wrapThrough;
745  else
746  SAL_WARN("sw.ww8",
747  "DocxSdrExport::startDMLAnchorInline: unexpected EG_WrapType value");
748 
749  m_pImpl->getSerializer()->startElementNS(XML_wp, nWrapToken, XML_wrapText, "bothSides");
750 
751  it = aGrabBag.find("CT_WrapPath");
752  if (it != aGrabBag.end())
753  {
754  m_pImpl->getSerializer()->startElementNS(XML_wp, XML_wrapPolygon, XML_edited, "0");
755  auto aSeqSeq = it->second.get<drawing::PointSequenceSequence>();
756  auto aPoints(comphelper::sequenceToContainer<std::vector<awt::Point>>(aSeqSeq[0]));
757  for (auto i = aPoints.begin(); i != aPoints.end(); ++i)
758  {
759  awt::Point& rPoint = *i;
760  m_pImpl->getSerializer()->singleElementNS(
761  XML_wp, (i == aPoints.begin() ? XML_start : XML_lineTo), XML_x,
762  OString::number(rPoint.X), XML_y, OString::number(rPoint.Y));
763  }
764  m_pImpl->getSerializer()->endElementNS(XML_wp, XML_wrapPolygon);
765  }
766 
767  m_pImpl->getSerializer()->endElementNS(XML_wp, nWrapToken);
768  }
769  }
770 
771  // Or if we have a contour.
772  if (!nWrapToken && pFrameFormat->GetSurround().IsContour())
773  {
774  if (const SwNoTextNode* pNd = sw::util::GetNoTextNodeFromSwFrameFormat(*pFrameFormat))
775  {
776  const tools::PolyPolygon* pPolyPoly = pNd->HasContour();
777  if (pPolyPoly && pPolyPoly->Count())
778  {
779  nWrapToken = XML_wrapTight;
780  m_pImpl->getSerializer()->startElementNS(XML_wp, nWrapToken, XML_wrapText,
781  "bothSides");
782 
783  m_pImpl->getSerializer()->startElementNS(XML_wp, XML_wrapPolygon, XML_edited, "0");
785  *pPolyPoly, pNd, /*bCorrectCrop=*/true);
786  for (sal_uInt16 i = 0; i < aPoly.GetSize(); ++i)
787  m_pImpl->getSerializer()->singleElementNS(
788  XML_wp, (i == 0 ? XML_start : XML_lineTo), XML_x,
789  OString::number(aPoly[i].X()), XML_y, OString::number(aPoly[i].Y()));
790  m_pImpl->getSerializer()->endElementNS(XML_wp, XML_wrapPolygon);
791 
792  m_pImpl->getSerializer()->endElementNS(XML_wp, nWrapToken);
793  }
794  }
795  }
796 
797  // No? Then just approximate based on what we have.
798  if (!isAnchor || nWrapToken)
799  return;
800 
801  switch (pFrameFormat->GetSurround().GetValue())
802  {
803  case css::text::WrapTextMode_NONE:
804  m_pImpl->getSerializer()->singleElementNS(XML_wp, XML_wrapTopAndBottom);
805  break;
806  case css::text::WrapTextMode_THROUGH:
807  m_pImpl->getSerializer()->singleElementNS(XML_wp, XML_wrapNone);
808  break;
809  case css::text::WrapTextMode_PARALLEL:
810  m_pImpl->getSerializer()->singleElementNS(XML_wp, XML_wrapSquare, XML_wrapText,
811  "bothSides");
812  break;
813  case css::text::WrapTextMode_DYNAMIC:
814  default:
815  m_pImpl->getSerializer()->singleElementNS(XML_wp, XML_wrapSquare, XML_wrapText,
816  "largest");
817  break;
818  }
819 }
820 
822 {
823  bool isAnchor;
824  if (m_pImpl->getFlyFrameGraphic())
825  {
826  isAnchor = false; // end Inline Graphic object inside DMLTextFrame
827  }
828  else
829  {
830  isAnchor = pFrameFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR;
831  }
832  m_pImpl->getSerializer()->endElementNS(XML_wp, isAnchor ? XML_anchor : XML_inline);
833 
834  m_pImpl->getSerializer()->endElementNS(XML_w, XML_drawing);
835  m_pImpl->setDrawingOpen(false);
836 }
837 
838 void DocxSdrExport::writeVMLDrawing(const SdrObject* sdrObj, const SwFrameFormat& rFrameFormat)
839 {
840  m_pImpl->getSerializer()->startElementNS(XML_w, XML_pict);
841  m_pImpl->getDrawingML()->SetFS(m_pImpl->getSerializer());
842  // See WinwordAnchoring::SetAnchoring(), these are not part of the SdrObject, have to be passed around manually.
843 
844  const SwFormatHoriOrient& rHoriOri = rFrameFormat.GetHoriOrient();
845  const SwFormatVertOrient& rVertOri = rFrameFormat.GetVertOrient();
846  SwFormatSurround const& rSurround(rFrameFormat.GetSurround());
847 
848  std::unique_ptr<sax_fastparser::FastAttributeList> pAttrList(
849  docx::SurroundToVMLWrap(rSurround));
850  m_pImpl->getExport().VMLExporter().AddSdrObject(
851  *sdrObj, rHoriOri.GetHoriOrient(), rVertOri.GetVertOrient(), rHoriOri.GetRelationOrient(),
852  rVertOri.GetRelationOrient(), std::move(pAttrList), true);
853  m_pImpl->getSerializer()->endElementNS(XML_w, XML_pict);
854 }
855 
856 static bool lcl_isLockedCanvas(const uno::Reference<drawing::XShape>& xShape)
857 {
858  uno::Sequence<beans::PropertyValue> propList = lclGetProperty(xShape, "InteropGrabBag");
859  /*
860  * Export as Locked Canvas only if the property
861  * is in the PropertySet
862  */
863  return std::any_of(propList.begin(), propList.end(), [](const beans::PropertyValue& rProp) {
864  return rProp.Name == "LockedCanvas";
865  });
866 }
867 
868 void DocxSdrExport::writeDMLDrawing(const SdrObject* pSdrObject, const SwFrameFormat* pFrameFormat,
869  int nAnchorId)
870 {
871  uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pSdrObject)->getUnoShape(),
872  uno::UNO_QUERY_THROW);
873  if (!Impl::isSupportedDMLShape(xShape))
874  return;
875 
876  m_pImpl->getExport().DocxAttrOutput().GetSdtEndBefore(pSdrObject);
877 
878  sax_fastparser::FSHelperPtr pFS = m_pImpl->getSerializer();
879  Size aSize(pSdrObject->GetLogicRect().GetWidth(), pSdrObject->GetLogicRect().GetHeight());
880  startDMLAnchorInline(pFrameFormat, aSize);
881 
882  sax_fastparser::FastAttributeList* pDocPrAttrList
884  pDocPrAttrList->add(XML_id, OString::number(nAnchorId).getStr());
885  pDocPrAttrList->add(XML_name,
886  OUStringToOString(pSdrObject->GetName(), RTL_TEXTENCODING_UTF8).getStr());
887  if (!pSdrObject->GetTitle().isEmpty())
888  pDocPrAttrList->add(XML_title,
889  OUStringToOString(pSdrObject->GetTitle(), RTL_TEXTENCODING_UTF8));
890  if (!pSdrObject->GetDescription().isEmpty())
891  pDocPrAttrList->add(XML_descr,
892  OUStringToOString(pSdrObject->GetDescription(), RTL_TEXTENCODING_UTF8));
893  if (!pSdrObject->IsVisible()
894  && pFrameFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR)
895 
896  pDocPrAttrList->add(XML_hidden, OString::number(1).getStr());
897  sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList);
898  pFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef);
899 
900  uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY_THROW);
901  const char* pNamespace = "http://schemas.microsoft.com/office/word/2010/wordprocessingShape";
902  if (xServiceInfo->supportsService("com.sun.star.drawing.GroupShape"))
903  pNamespace = "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup";
904  else if (xServiceInfo->supportsService("com.sun.star.drawing.GraphicObjectShape"))
905  pNamespace = "http://schemas.openxmlformats.org/drawingml/2006/picture";
906  pFS->startElementNS(XML_a, XML_graphic, FSNS(XML_xmlns, XML_a),
907  m_pImpl->getExport().GetFilter().getNamespaceURL(OOX_NS(dml)));
908  pFS->startElementNS(XML_a, XML_graphicData, XML_uri, pNamespace);
909 
910  bool bLockedCanvas = lcl_isLockedCanvas(xShape);
911  if (bLockedCanvas)
912  pFS->startElementNS(
913  XML_lc, XML_lockedCanvas, FSNS(XML_xmlns, XML_lc),
914  m_pImpl->getExport().GetFilter().getNamespaceURL(OOX_NS(dmlLockedCanvas)));
915 
916  m_pImpl->getExport().OutputDML(xShape);
917 
918  if (bLockedCanvas)
919  pFS->endElementNS(XML_lc, XML_lockedCanvas);
920  pFS->endElementNS(XML_a, XML_graphicData);
921  pFS->endElementNS(XML_a, XML_graphic);
922 
923  // Relative size of the drawing.
924  if (pSdrObject->GetRelativeWidth())
925  {
926  // At the moment drawinglayer objects are always relative from page.
927  OUString sValue;
928  switch (pSdrObject->GetRelativeWidthRelation())
929  {
930  case text::RelOrientation::FRAME:
931  sValue = "margin";
932  break;
933  case text::RelOrientation::PAGE_LEFT:
934  if (pFrameFormat->GetDoc()->GetPageDesc(0).GetUseOn() == UseOnPage::Mirror)
935  sValue = "outsideMargin";
936  else
937  sValue = "leftMargin";
938  break;
939  case text::RelOrientation::PAGE_RIGHT:
940  if (pFrameFormat->GetDoc()->GetPageDesc(0).GetUseOn() == UseOnPage::Mirror)
941  sValue = "insideMargin";
942  else
943  sValue = "rightMargin";
944  break;
945  case text::RelOrientation::PAGE_FRAME:
946  default:
947  sValue = "page";
948  break;
949  }
950  pFS->startElementNS(XML_wp14, XML_sizeRelH, XML_relativeFrom, sValue);
951  pFS->startElementNS(XML_wp14, XML_pctWidth);
952  pFS->writeEscaped(
953  OUString::number(*pSdrObject->GetRelativeWidth() * 100 * oox::drawingml::PER_PERCENT));
954  pFS->endElementNS(XML_wp14, XML_pctWidth);
955  pFS->endElementNS(XML_wp14, XML_sizeRelH);
956  }
957  if (pSdrObject->GetRelativeHeight())
958  {
959  OUString sValue;
960  switch (pSdrObject->GetRelativeHeightRelation())
961  {
962  case text::RelOrientation::FRAME:
963  sValue = "margin";
964  break;
965  case text::RelOrientation::PAGE_PRINT_AREA:
966  sValue = "topMargin";
967  break;
968  case text::RelOrientation::PAGE_PRINT_AREA_BOTTOM:
969  sValue = "bottomMargin";
970  break;
971  case text::RelOrientation::PAGE_FRAME:
972  default:
973  sValue = "page";
974  break;
975  }
976  pFS->startElementNS(XML_wp14, XML_sizeRelV, XML_relativeFrom, sValue);
977  pFS->startElementNS(XML_wp14, XML_pctHeight);
978  pFS->writeEscaped(
979  OUString::number(*pSdrObject->GetRelativeHeight() * 100 * oox::drawingml::PER_PERCENT));
980  pFS->endElementNS(XML_wp14, XML_pctHeight);
981  pFS->endElementNS(XML_wp14, XML_sizeRelV);
982  }
983 
984  endDMLAnchorInline(pFrameFormat);
985 }
986 
988 {
989  const SvxShadowItem& aShadowItem = rFrameFormat.GetShadow();
990  if (aShadowItem.GetLocation() == SvxShadowLocation::NONE)
991  return;
992 
993  OString aShadowWidth(OString::number(double(aShadowItem.GetWidth()) / 20) + "pt");
994  OString aOffset;
995  switch (aShadowItem.GetLocation())
996  {
997  case SvxShadowLocation::TopLeft:
998  aOffset = "-" + aShadowWidth + ",-" + aShadowWidth;
999  break;
1000  case SvxShadowLocation::TopRight:
1001  aOffset = aShadowWidth + ",-" + aShadowWidth;
1002  break;
1003  case SvxShadowLocation::BottomLeft:
1004  aOffset = "-" + aShadowWidth + "," + aShadowWidth;
1005  break;
1006  case SvxShadowLocation::BottomRight:
1007  aOffset = aShadowWidth + "," + aShadowWidth;
1008  break;
1009  case SvxShadowLocation::NONE:
1010  case SvxShadowLocation::End:
1011  break;
1012  }
1013  if (aOffset.isEmpty())
1014  return;
1015 
1016  OString aShadowColor = msfilter::util::ConvertColor(aShadowItem.GetColor());
1017  m_pSerializer->singleElementNS(XML_v, XML_shadow, XML_on, "t", XML_color, "#" + aShadowColor,
1018  XML_offset, aOffset);
1019 }
1020 
1021 bool DocxSdrExport::Impl::isSupportedDMLShape(const uno::Reference<drawing::XShape>& xShape)
1022 {
1023  uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY_THROW);
1024  if (xServiceInfo->supportsService("com.sun.star.drawing.PolyPolygonShape")
1025  || xServiceInfo->supportsService("com.sun.star.drawing.PolyLineShape"))
1026  return false;
1027 
1028  // For signature line shapes, we don't want DML, just the VML shape.
1029  if (xServiceInfo->supportsService("com.sun.star.drawing.GraphicObjectShape"))
1030  {
1031  uno::Reference<beans::XPropertySet> xShapeProperties(xShape, uno::UNO_QUERY);
1032  bool bIsSignatureLineShape = false;
1033  xShapeProperties->getPropertyValue("IsSignatureLine") >>= bIsSignatureLineShape;
1034  if (bIsSignatureLineShape)
1035  return false;
1036  }
1037 
1038  return true;
1039 }
1040 
1042  const SwFrameFormat& rFrameFormat, int nAnchorId)
1043 {
1044  bool bDMLAndVMLDrawingOpen = m_pImpl->getDMLAndVMLDrawingOpen();
1045  m_pImpl->setDMLAndVMLDrawingOpen(true);
1046 
1047  // Depending on the shape type, we actually don't write the shape as DML.
1048  OUString sShapeType;
1049  ShapeFlag nMirrorFlags = ShapeFlag::NONE;
1050  uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(sdrObj)->getUnoShape(),
1051  uno::UNO_QUERY_THROW);
1052 
1053  MSO_SPT eShapeType
1054  = EscherPropertyContainer::GetCustomShapeType(xShape, nMirrorFlags, sShapeType);
1055 
1056  // In case we are already inside a DML block, then write the shape only as VML, turn out that's allowed to do.
1057  // A common service created in util to check for VML shapes which are allowed to have textbox in content
1059  && (!bDMLAndVMLDrawingOpen || lcl_isLockedCanvas(xShape))) // Locked canvas is OK inside DML
1060  {
1061  m_pImpl->getSerializer()->startElementNS(XML_mc, XML_AlternateContent);
1062 
1063  auto pObjGroup = dynamic_cast<const SdrObjGroup*>(sdrObj);
1064  m_pImpl->getSerializer()->startElementNS(XML_mc, XML_Choice, XML_Requires,
1065  (pObjGroup ? "wpg" : "wps"));
1066  writeDMLDrawing(sdrObj, &rFrameFormat, nAnchorId);
1067  m_pImpl->getSerializer()->endElementNS(XML_mc, XML_Choice);
1068 
1069  m_pImpl->getSerializer()->startElementNS(XML_mc, XML_Fallback);
1070  writeVMLDrawing(sdrObj, rFrameFormat);
1071  m_pImpl->getSerializer()->endElementNS(XML_mc, XML_Fallback);
1072 
1073  m_pImpl->getSerializer()->endElementNS(XML_mc, XML_AlternateContent);
1074  }
1075  else
1076  writeVMLDrawing(sdrObj, rFrameFormat);
1077 
1078  m_pImpl->setDMLAndVMLDrawingOpen(bDMLAndVMLDrawingOpen);
1079 }
1080 
1081 // Converts ARGB transparency (0..255) to drawingml alpha (opposite, and 0..100000)
1082 static OString lcl_TransparencyToDrawingMlAlpha(const Color& rColor)
1083 {
1084  if (rColor.IsTransparent())
1085  {
1086  sal_Int32 nAlphaPercent = float(rColor.GetAlpha()) / 2.55;
1087  return OString::number(nAlphaPercent * oox::drawingml::PER_PERCENT);
1088  }
1089 
1090  return OString();
1091 }
1092 
1094 {
1095  const SvxShadowItem& aShadowItem = rFrameFormat.GetShadow();
1096 
1097  // Output effects
1098  if (aShadowItem.GetLocation() == SvxShadowLocation::NONE)
1099  return;
1100 
1101  // Distance is measured diagonally from corner
1102  double nShadowDist
1103  = sqrt(static_cast<double>(aShadowItem.GetWidth()) * aShadowItem.GetWidth() * 2.0);
1104  OString aShadowDist(OString::number(TwipsToEMU(nShadowDist)));
1105  OString aShadowColor = msfilter::util::ConvertColor(aShadowItem.GetColor());
1106  OString aShadowAlpha = lcl_TransparencyToDrawingMlAlpha(aShadowItem.GetColor());
1107  sal_uInt32 nShadowDir = 0;
1108  switch (aShadowItem.GetLocation())
1109  {
1110  case SvxShadowLocation::TopLeft:
1111  nShadowDir = 13500000;
1112  break;
1113  case SvxShadowLocation::TopRight:
1114  nShadowDir = 18900000;
1115  break;
1116  case SvxShadowLocation::BottomLeft:
1117  nShadowDir = 8100000;
1118  break;
1119  case SvxShadowLocation::BottomRight:
1120  nShadowDir = 2700000;
1121  break;
1122  case SvxShadowLocation::NONE:
1123  case SvxShadowLocation::End:
1124  break;
1125  }
1126  OString aShadowDir(OString::number(nShadowDir));
1127 
1128  m_pImpl->getSerializer()->startElementNS(XML_a, XML_effectLst);
1129  m_pImpl->getSerializer()->startElementNS(XML_a, XML_outerShdw, XML_dist, aShadowDist, XML_dir,
1130  aShadowDir);
1131  if (aShadowAlpha.isEmpty())
1132  m_pImpl->getSerializer()->singleElementNS(XML_a, XML_srgbClr, XML_val, aShadowColor);
1133  else
1134  {
1135  m_pImpl->getSerializer()->startElementNS(XML_a, XML_srgbClr, XML_val, aShadowColor);
1136  m_pImpl->getSerializer()->singleElementNS(XML_a, XML_alpha, XML_val, aShadowAlpha);
1137  m_pImpl->getSerializer()->endElementNS(XML_a, XML_srgbClr);
1138  }
1139  m_pImpl->getSerializer()->endElementNS(XML_a, XML_outerShdw);
1140  m_pImpl->getSerializer()->endElementNS(XML_a, XML_effectLst);
1141 }
1142 
1143 void DocxSdrExport::writeDiagram(const SdrObject* sdrObject, const SwFrameFormat& rFrameFormat,
1144  int nDiagramId)
1145 {
1146  uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(sdrObject)->getUnoShape(),
1147  uno::UNO_QUERY);
1148 
1149  // write necessary tags to document.xml
1150  Size aSize(sdrObject->GetSnapRect().GetWidth(), sdrObject->GetSnapRect().GetHeight());
1151  startDMLAnchorInline(&rFrameFormat, aSize);
1152 
1153  m_pImpl->getDrawingML()->WriteDiagram(xShape, nDiagramId);
1154 
1155  endDMLAnchorInline(&rFrameFormat);
1156 }
1157 
1159 {
1160  const SwFrameFormat& rFrameFormat = pParentFrame->GetFrameFormat();
1161  const SwNodeIndex* pNodeIndex = rFrameFormat.GetContent().GetContentIdx();
1162 
1163  sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex() + 1 : 0;
1164  sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1165 
1166  //Save data here and restore when out of scope
1167  ExportDataSaveRestore aDataGuard(m_pImpl->getExport(), nStt, nEnd, pParentFrame);
1168 
1170  ::comphelper::FlagRestorationGuard const g(m_pImpl->m_bFlyFrameGraphic, true);
1171  comphelper::ValueRestorationGuard vg(m_pImpl->getExport().m_nTextTyp, TXT_TXTBOX);
1172  m_pImpl->getExport().WriteText();
1173 }
1174 
1176 {
1177  const editeng::SvxBorderLine* pBorderLine = nullptr;
1178 
1179  if (rBox.GetTop())
1180  {
1181  pBorderLine = rBox.GetTop();
1182  }
1183  else if (rBox.GetLeft())
1184  {
1185  pBorderLine = rBox.GetLeft();
1186  }
1187  else if (rBox.GetBottom())
1188  {
1189  pBorderLine = rBox.GetBottom();
1190  }
1191  else if (rBox.GetRight())
1192  {
1193  pBorderLine = rBox.GetRight();
1194  }
1195 
1196  if (!pBorderLine)
1197  {
1198  return;
1199  }
1200 
1201  sax_fastparser::FSHelperPtr pFS = m_pImpl->getSerializer();
1202  double fConverted(editeng::ConvertBorderWidthToWord(pBorderLine->GetBorderLineStyle(),
1203  pBorderLine->GetWidth()));
1204  OString sWidth(OString::number(TwipsToEMU(fConverted)));
1205  pFS->startElementNS(XML_a, XML_ln, XML_w, sWidth);
1206 
1207  pFS->startElementNS(XML_a, XML_solidFill);
1208  OString sColor(msfilter::util::ConvertColor(pBorderLine->GetColor()));
1209  pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, sColor);
1210  pFS->endElementNS(XML_a, XML_solidFill);
1211 
1212  if (SvxBorderLineStyle::DASHED == pBorderLine->GetBorderLineStyle()) // Line Style is Dash type
1213  pFS->singleElementNS(XML_a, XML_prstDash, XML_val, "dash");
1214 
1215  pFS->endElementNS(XML_a, XML_ln);
1216 }
1217 
1218 void DocxSdrExport::writeDMLTextFrame(ww8::Frame const* pParentFrame, int nAnchorId,
1219  bool bTextBoxOnly)
1220 {
1221  bool bDMLAndVMLDrawingOpen = m_pImpl->getDMLAndVMLDrawingOpen();
1222  m_pImpl->setDMLAndVMLDrawingOpen(IsAnchorTypeInsideParagraph(pParentFrame));
1223 
1224  sax_fastparser::FSHelperPtr pFS = m_pImpl->getSerializer();
1225  const SwFrameFormat& rFrameFormat = pParentFrame->GetFrameFormat();
1226  const SwNodeIndex* pNodeIndex = rFrameFormat.GetContent().GetContentIdx();
1227 
1228  sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex() + 1 : 0;
1229  sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1230 
1231  //Save data here and restore when out of scope
1232  ExportDataSaveRestore aDataGuard(m_pImpl->getExport(), nStt, nEnd, pParentFrame);
1233 
1234  // When a frame has some low height, but automatically expanded due
1235  // to lots of contents, this size contains the real size.
1236  const Size aSize = pParentFrame->GetSize();
1237 
1238  uno::Reference<drawing::XShape> xShape;
1239  const SdrObject* pSdrObj = rFrameFormat.FindRealSdrObject();
1240  if (pSdrObj)
1241  xShape.set(const_cast<SdrObject*>(pSdrObj)->getUnoShape(), uno::UNO_QUERY);
1242  uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
1243  uno::Reference<beans::XPropertySetInfo> xPropSetInfo;
1244  if (xPropertySet.is())
1245  xPropSetInfo = xPropertySet->getPropertySetInfo();
1246 
1248  {
1249  drawing::TextVerticalAdjust eAdjust = drawing::TextVerticalAdjust_TOP;
1250  if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("TextVerticalAdjust"))
1251  xPropertySet->getPropertyValue("TextVerticalAdjust") >>= eAdjust;
1252  m_pImpl->getBodyPrAttrList()->add(XML_anchor,
1254  }
1255 
1256  if (!bTextBoxOnly)
1257  {
1258  startDMLAnchorInline(&rFrameFormat, aSize);
1259 
1260  sax_fastparser::FastAttributeList* pDocPrAttrList
1262  pDocPrAttrList->add(XML_id, OString::number(nAnchorId).getStr());
1263  pDocPrAttrList->add(
1264  XML_name, OUStringToOString(rFrameFormat.GetName(), RTL_TEXTENCODING_UTF8).getStr());
1265  sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList);
1266  pFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef);
1267 
1268  pFS->startElementNS(XML_a, XML_graphic, FSNS(XML_xmlns, XML_a),
1269  m_pImpl->getExport().GetFilter().getNamespaceURL(OOX_NS(dml)));
1270  pFS->startElementNS(XML_a, XML_graphicData, XML_uri,
1271  "http://schemas.microsoft.com/office/word/2010/wordprocessingShape");
1272  pFS->startElementNS(XML_wps, XML_wsp);
1273  pFS->singleElementNS(XML_wps, XML_cNvSpPr, XML_txBox, "1");
1274 
1275  uno::Any aRotation;
1276  m_pImpl->setDMLandVMLTextFrameRotation(0_deg100);
1277  if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag"))
1278  {
1279  uno::Sequence<beans::PropertyValue> propList;
1280  xPropertySet->getPropertyValue("FrameInteropGrabBag") >>= propList;
1281  auto pProp = std::find_if(propList.begin(), propList.end(),
1282  [](const beans::PropertyValue& rProp) {
1283  return rProp.Name == "mso-rotation-angle";
1284  });
1285  if (pProp != propList.end())
1286  aRotation = pProp->Value;
1287  }
1288  sal_Int32 nTmp;
1289  if (aRotation >>= nTmp)
1290  m_pImpl->getDMLandVMLTextFrameRotation() = Degree100(nTmp);
1291  OString sRotation(OString::number(
1292  oox::drawingml::ExportRotateClockwisify(m_pImpl->getDMLandVMLTextFrameRotation())));
1293  // Shape properties
1294  pFS->startElementNS(XML_wps, XML_spPr);
1295  if (m_pImpl->getDMLandVMLTextFrameRotation())
1296  {
1297  pFS->startElementNS(XML_a, XML_xfrm, XML_rot, sRotation);
1298  }
1299  else
1300  {
1301  pFS->startElementNS(XML_a, XML_xfrm);
1302  }
1303  pFS->singleElementNS(XML_a, XML_off, XML_x, "0", XML_y, "0");
1304  OString aWidth(OString::number(TwipsToEMU(aSize.Width())));
1305  OString aHeight(OString::number(TwipsToEMU(aSize.Height())));
1306  pFS->singleElementNS(XML_a, XML_ext, XML_cx, aWidth, XML_cy, aHeight);
1307  pFS->endElementNS(XML_a, XML_xfrm);
1308  OUString shapeType = "rect";
1309  if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag"))
1310  {
1311  uno::Sequence<beans::PropertyValue> propList;
1312  xPropertySet->getPropertyValue("FrameInteropGrabBag") >>= propList;
1313  auto pProp = std::find_if(propList.begin(), propList.end(),
1314  [](const beans::PropertyValue& rProp) {
1315  return rProp.Name == "mso-orig-shape-type";
1316  });
1317  if (pProp != propList.end())
1318  pProp->Value >>= shapeType;
1319  }
1320  //Empty shapeType will lead to corruption so to avoid that shapeType is set to default i.e. "rect"
1321  if (shapeType.isEmpty())
1322  shapeType = "rect";
1323 
1324  pFS->singleElementNS(XML_a, XML_prstGeom, XML_prst, shapeType);
1325  m_pImpl->setDMLTextFrameSyntax(true);
1326  m_pImpl->getExport().OutputFormat(pParentFrame->GetFrameFormat(), false, false, true);
1327  m_pImpl->setDMLTextFrameSyntax(false);
1328  writeDMLEffectLst(rFrameFormat);
1329  pFS->endElementNS(XML_wps, XML_spPr);
1330  }
1331 
1332  //first, loop through ALL of the chained textboxes to identify a unique ID for each chain, and sequence number for each textbox in that chain.
1333  if (!m_pImpl->getExport().m_bLinkedTextboxesHelperInitialized)
1334  {
1335  sal_Int32 nSeq = 0;
1336  for (auto& rEntry : m_pImpl->getExport().m_aLinkedTextboxesHelper)
1337  {
1338  //find the start of a textbox chain: has no PREVIOUS link, but does have NEXT link
1339  if (rEntry.second.sPrevChain.isEmpty() && !rEntry.second.sNextChain.isEmpty())
1340  {
1341  //assign this chain a unique ID and start a new sequence
1342  nSeq = 0;
1343  rEntry.second.nId = ++m_pImpl->getExport().m_nLinkedTextboxesChainId;
1344  rEntry.second.nSeq = nSeq;
1345 
1346  OUString sCheckForBrokenChains = rEntry.first;
1347 
1348  //follow the chain and assign the same id, and incremental sequence numbers.
1349  auto followChainIter
1350  = m_pImpl->getExport().m_aLinkedTextboxesHelper.find(rEntry.second.sNextChain);
1351  while (followChainIter != m_pImpl->getExport().m_aLinkedTextboxesHelper.end())
1352  {
1353  //verify that the NEXT textbox also points to me as the PREVIOUS.
1354  // A broken link indicates a leftover remnant that can be ignored.
1355  if (followChainIter->second.sPrevChain != sCheckForBrokenChains)
1356  break;
1357 
1358  followChainIter->second.nId = m_pImpl->getExport().m_nLinkedTextboxesChainId;
1359  followChainIter->second.nSeq = ++nSeq;
1360 
1361  //empty next chain indicates the end of the linked chain.
1362  if (followChainIter->second.sNextChain.isEmpty())
1363  break;
1364 
1365  sCheckForBrokenChains = followChainIter->first;
1366  followChainIter = m_pImpl->getExport().m_aLinkedTextboxesHelper.find(
1367  followChainIter->second.sNextChain);
1368  }
1369  }
1370  }
1371  m_pImpl->getExport().m_bLinkedTextboxesHelperInitialized = true;
1372  }
1373 
1374  m_pImpl->getExport().m_pParentFrame = nullptr;
1375  bool skipTxBxContent = false;
1376  bool isTxbxLinked = false;
1377 
1378  OUString sLinkChainName;
1379  if (xPropSetInfo.is())
1380  {
1381  if (xPropSetInfo->hasPropertyByName("LinkDisplayName"))
1382  xPropertySet->getPropertyValue("LinkDisplayName") >>= sLinkChainName;
1383  else if (xPropSetInfo->hasPropertyByName("ChainName"))
1384  xPropertySet->getPropertyValue("ChainName") >>= sLinkChainName;
1385  }
1386 
1387  // second, check if THIS textbox is linked and then decide whether to write the tag txbx or linkedTxbx
1388  auto linkedTextboxesIter = m_pImpl->getExport().m_aLinkedTextboxesHelper.find(sLinkChainName);
1389  if (linkedTextboxesIter != m_pImpl->getExport().m_aLinkedTextboxesHelper.end())
1390  {
1391  if ((linkedTextboxesIter->second.nId != 0) && (linkedTextboxesIter->second.nSeq != 0))
1392  {
1393  //not the first in the chain, so write the tag as linkedTxbx
1394  pFS->singleElementNS(XML_wps, XML_linkedTxbx, XML_id,
1395  OString::number(linkedTextboxesIter->second.nId), XML_seq,
1396  OString::number(linkedTextboxesIter->second.nSeq));
1397  /* no text content should be added to this tag,
1398  since the textbox is linked, the entire content
1399  is written in txbx block
1400  */
1401  skipTxBxContent = true;
1402  }
1403  else if ((linkedTextboxesIter->second.nId != 0) && (linkedTextboxesIter->second.nSeq == 0))
1404  {
1405  /* this is the first textbox in the chaining, we add the text content
1406  to this block*/
1407  //since the text box is linked, it needs an id.
1408  pFS->startElementNS(XML_wps, XML_txbx, XML_id,
1409  OString::number(linkedTextboxesIter->second.nId));
1410  isTxbxLinked = true;
1411  }
1412  }
1413 
1414  if (!skipTxBxContent)
1415  {
1416  if (!isTxbxLinked)
1417  pFS->startElementNS(XML_wps, XML_txbx); //text box is not linked, therefore no id.
1418 
1419  pFS->startElementNS(XML_w, XML_txbxContent);
1420 
1421  const SvxFrameDirectionItem& rDirection = rFrameFormat.GetFrameDir();
1422  if (rDirection.GetValue() == SvxFrameDirection::Vertical_RL_TB)
1423  m_pImpl->getBodyPrAttrList()->add(XML_vert, "eaVert");
1424  else if (rDirection.GetValue() == SvxFrameDirection::Vertical_LR_BT)
1425  m_pImpl->getBodyPrAttrList()->add(XML_vert, "vert270");
1426 
1427  {
1428  ::comphelper::FlagRestorationGuard const g(m_pImpl->m_bFlyFrameGraphic, true);
1429  comphelper::ValueRestorationGuard vg(m_pImpl->getExport().m_nTextTyp, TXT_TXTBOX);
1430  m_pImpl->getExport().WriteText();
1431  if (m_pImpl->getParagraphSdtOpen())
1432  {
1433  m_pImpl->getExport().DocxAttrOutput().EndParaSdtBlock();
1434  m_pImpl->setParagraphSdtOpen(false);
1435  }
1436  }
1437 
1438  pFS->endElementNS(XML_w, XML_txbxContent);
1439  pFS->endElementNS(XML_wps, XML_txbx);
1440  }
1441 
1442  // We need to init padding to 0, if it's not set.
1443  // In LO the default is 0 and so ins attributes are not set when padding is 0
1444  // but in MSO the default is 254 / 127, so we need to set 0 padding explicitly
1445  if (m_pImpl->getBodyPrAttrList())
1446  {
1447  if (!m_pImpl->getBodyPrAttrList()->hasAttribute(XML_lIns))
1448  m_pImpl->getBodyPrAttrList()->add(XML_lIns, OString::number(0));
1449  if (!m_pImpl->getBodyPrAttrList()->hasAttribute(XML_tIns))
1450  m_pImpl->getBodyPrAttrList()->add(XML_tIns, OString::number(0));
1451  if (!m_pImpl->getBodyPrAttrList()->hasAttribute(XML_rIns))
1452  m_pImpl->getBodyPrAttrList()->add(XML_rIns, OString::number(0));
1453  if (!m_pImpl->getBodyPrAttrList()->hasAttribute(XML_bIns))
1454  m_pImpl->getBodyPrAttrList()->add(XML_bIns, OString::number(0));
1455  }
1456 
1457  sax_fastparser::XFastAttributeListRef xBodyPrAttrList(m_pImpl->getBodyPrAttrList());
1458  m_pImpl->setBodyPrAttrList(nullptr);
1459  if (!bTextBoxOnly)
1460  {
1461  pFS->startElementNS(XML_wps, XML_bodyPr, xBodyPrAttrList);
1462  // AutoSize of the Text Frame.
1463  const SwFormatFrameSize& rSize = rFrameFormat.GetFrameSize();
1464  pFS->singleElementNS(
1465  XML_a,
1466  (rSize.GetHeightSizeType() == SwFrameSize::Variable ? XML_spAutoFit : XML_noAutofit));
1467  pFS->endElementNS(XML_wps, XML_bodyPr);
1468 
1469  pFS->endElementNS(XML_wps, XML_wsp);
1470  pFS->endElementNS(XML_a, XML_graphicData);
1471  pFS->endElementNS(XML_a, XML_graphic);
1472 
1473  // Relative size of the Text Frame.
1474  const sal_uInt8 nWidthPercent = rSize.GetWidthPercent();
1475  if (nWidthPercent && nWidthPercent != SwFormatFrameSize::SYNCED)
1476  {
1477  pFS->startElementNS(XML_wp14, XML_sizeRelH, XML_relativeFrom,
1478  (rSize.GetWidthPercentRelation() == text::RelOrientation::PAGE_FRAME
1479  ? "page"
1480  : "margin"));
1481  pFS->startElementNS(XML_wp14, XML_pctWidth);
1482  pFS->writeEscaped(OUString::number(nWidthPercent * oox::drawingml::PER_PERCENT));
1483  pFS->endElementNS(XML_wp14, XML_pctWidth);
1484  pFS->endElementNS(XML_wp14, XML_sizeRelH);
1485  }
1486  const sal_uInt8 nHeightPercent = rSize.GetHeightPercent();
1487  if (nHeightPercent && nHeightPercent != SwFormatFrameSize::SYNCED)
1488  {
1489  pFS->startElementNS(
1490  XML_wp14, XML_sizeRelV, XML_relativeFrom,
1491  (rSize.GetHeightPercentRelation() == text::RelOrientation::PAGE_FRAME ? "page"
1492  : "margin"));
1493  pFS->startElementNS(XML_wp14, XML_pctHeight);
1494  pFS->writeEscaped(OUString::number(nHeightPercent * oox::drawingml::PER_PERCENT));
1495  pFS->endElementNS(XML_wp14, XML_pctHeight);
1496  pFS->endElementNS(XML_wp14, XML_sizeRelV);
1497  }
1498 
1499  endDMLAnchorInline(&rFrameFormat);
1500  }
1501  m_pImpl->setDMLAndVMLDrawingOpen(bDMLAndVMLDrawingOpen);
1502 }
1503 
1504 void DocxSdrExport::writeVMLTextFrame(ww8::Frame const* pParentFrame, bool bTextBoxOnly)
1505 {
1506  bool bDMLAndVMLDrawingOpen = m_pImpl->getDMLAndVMLDrawingOpen();
1507  m_pImpl->setDMLAndVMLDrawingOpen(IsAnchorTypeInsideParagraph(pParentFrame));
1508 
1509  sax_fastparser::FSHelperPtr pFS = m_pImpl->getSerializer();
1510  const SwFrameFormat& rFrameFormat = pParentFrame->GetFrameFormat();
1511  const SwNodeIndex* pNodeIndex = rFrameFormat.GetContent().GetContentIdx();
1512 
1513  sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex() + 1 : 0;
1514  sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1515 
1516  //Save data here and restore when out of scope
1517  ExportDataSaveRestore aDataGuard(m_pImpl->getExport(), nStt, nEnd, pParentFrame);
1518 
1519  // When a frame has some low height, but automatically expanded due
1520  // to lots of contents, this size contains the real size.
1521  const Size aSize = pParentFrame->GetSize();
1522  m_pImpl->setFlyFrameSize(&aSize);
1523 
1524  m_pImpl->setTextFrameSyntax(true);
1527  m_pImpl->getTextFrameStyle() = "position:absolute";
1528  if (!bTextBoxOnly)
1529  {
1530  OString sRotation(OString::number(m_pImpl->getDMLandVMLTextFrameRotation().get() / -100));
1531  m_pImpl->getExport()
1532  .SdrExporter()
1533  .getTextFrameStyle()
1534  .append(";rotation:")
1535  .append(sRotation);
1536  }
1537  m_pImpl->getExport().OutputFormat(pParentFrame->GetFrameFormat(), false, false, true);
1538  m_pImpl->getFlyAttrList()->add(XML_style, m_pImpl->getTextFrameStyle().makeStringAndClear());
1539 
1540  const SdrObject* pObject = pParentFrame->GetFrameFormat().FindRealSdrObject();
1541  if (pObject != nullptr)
1542  {
1543  OUString sAnchorId = lclGetAnchorIdFromGrabBag(pObject);
1544  if (!sAnchorId.isEmpty())
1545  m_pImpl->getFlyAttrList()->addNS(XML_w14, XML_anchorId,
1546  OUStringToOString(sAnchorId, RTL_TEXTENCODING_UTF8));
1547  }
1548  sax_fastparser::XFastAttributeListRef xFlyAttrList(m_pImpl->getFlyAttrList().get());
1549  m_pImpl->getFlyAttrList().clear();
1550  sax_fastparser::XFastAttributeListRef xTextboxAttrList(m_pImpl->getTextboxAttrList().get());
1551  m_pImpl->getTextboxAttrList().clear();
1552  m_pImpl->setTextFrameSyntax(false);
1553  m_pImpl->setFlyFrameSize(nullptr);
1554  m_pImpl->getExport().m_pParentFrame = nullptr;
1555 
1556  if (!bTextBoxOnly)
1557  {
1558  pFS->startElementNS(XML_w, XML_pict);
1559  pFS->startElementNS(XML_v, XML_rect, xFlyAttrList);
1560  m_pImpl->textFrameShadow(rFrameFormat);
1561  if (m_pImpl->getFlyFillAttrList().is())
1562  {
1563  sax_fastparser::XFastAttributeListRef xFlyFillAttrList(
1564  m_pImpl->getFlyFillAttrList().get());
1565  m_pImpl->getFlyFillAttrList().clear();
1566  pFS->singleElementNS(XML_v, XML_fill, xFlyFillAttrList);
1567  }
1568  if (m_pImpl->getDashLineStyleAttr().is())
1569  {
1570  sax_fastparser::XFastAttributeListRef xDashLineStyleAttr(
1571  m_pImpl->getDashLineStyleAttr().get());
1572  m_pImpl->getDashLineStyleAttr().clear();
1573  pFS->singleElementNS(XML_v, XML_stroke, xDashLineStyleAttr);
1574  }
1575  pFS->startElementNS(XML_v, XML_textbox, xTextboxAttrList);
1576  }
1577  pFS->startElementNS(XML_w, XML_txbxContent);
1578  {
1579  ::comphelper::FlagRestorationGuard const g(m_pImpl->m_bFlyFrameGraphic, true);
1580  comphelper::ValueRestorationGuard vg(m_pImpl->getExport().m_nTextTyp, TXT_TXTBOX);
1581  m_pImpl->getExport().WriteText();
1582  if (m_pImpl->getParagraphSdtOpen())
1583  {
1584  m_pImpl->getExport().DocxAttrOutput().EndParaSdtBlock();
1585  m_pImpl->setParagraphSdtOpen(false);
1586  }
1587  }
1588  pFS->endElementNS(XML_w, XML_txbxContent);
1589  if (!bTextBoxOnly)
1590  {
1591  pFS->endElementNS(XML_v, XML_textbox);
1592 
1593  if (m_pImpl->getFlyWrapAttrList())
1594  {
1595  sax_fastparser::XFastAttributeListRef xFlyWrapAttrList(m_pImpl->getFlyWrapAttrList());
1596  m_pImpl->setFlyWrapAttrList(nullptr);
1597  pFS->singleElementNS(XML_w10, XML_wrap, xFlyWrapAttrList);
1598  }
1599 
1600  pFS->endElementNS(XML_v, XML_rect);
1601  pFS->endElementNS(XML_w, XML_pict);
1602  }
1603 
1604  m_pImpl->setDMLAndVMLDrawingOpen(bDMLAndVMLDrawingOpen);
1605 }
1606 
1607 bool DocxSdrExport::isTextBox(const SwFrameFormat& rFrameFormat)
1608 {
1609  return SwTextBoxHelper::isTextBox(&rFrameFormat, RES_FLYFRMFMT);
1610 }
1611 
1612 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt16 Count() const
bool getTextFrameSyntax() const
bool IsContour() const
Definition: fmtsrnd.hxx:53
void writeDMLAndVMLDrawing(const SdrObject *sdrObj, const SwFrameFormat &rFrameFormat, int nAnchorId)
Writes shape in both DML and VML format.
sax_fastparser::FastAttributeList * getFlyWrapAttrList() const
Helper class, so that the DocxExport::RestoreData() call will always happen.
SwNoTextNode * GetNoTextNodeFromSwFrameFormat(const SwFrameFormat &rFormat)
Get the SwNoTextNode associated with a SwFrameFormat if here is one.
static bool lcl_isLockedCanvas(const uno::Reference< drawing::XShape > &xShape)
sax_fastparser::FastAttributeList * m_pFlyWrapAttrList
bool getParagraphHasDrawing() const
bool IsDrawingOpen() const
sal_uInt8 GetAlpha() const
sal_uInt16 GetLower() const
const Size * m_pFlyFrameSize
static FastAttributeList * createAttrList()
double ConvertBorderWidthToWord(SvxBorderLineStyle, double)
std::unique_ptr< Impl > m_pImpl
TextVerticalAdjust GetTextVerticalAdjust(sal_Int32 nToken)
const sal_Int32 PER_PERCENT
void endDMLAnchorInline(const SwFrameFormat *pFrameFormat)
bool IsTransparent() const
css::uno::Reference< css::xml::sax::XFastAttributeList > XFastAttributeListRef
const SwFormatVertOrient & GetVertOrient(bool=true) const
Definition: fmtornt.hxx:106
oox::drawingml::DrawingML * m_pDrawingML
bool getDMLTextFrameSyntax() const
rtl::Reference< sax_fastparser::FastAttributeList > & getFlyAttrList()
sal_Int32 ExportRotateClockwisify(Degree100 input)
SwTwips GetPos() const
Definition: fmtornt.hxx:92
sal_uIntPtr sal_uLong
long Long
tools::Long GetRight() const
virtual void SaveData(sal_uLong nStt, sal_uLong nEnd)
Remember some of the members so that we can recurse in WriteText().
Definition: wrtww8.cxx:1887
void writeDMLEffectLst(const SwFrameFormat &rFrameFormat)
Write , the effect list.
OUString GetDescription() const
void addNS(sal_Int32 nNamespaceToken, sal_Int32 nToken, const OString &rValue)
OBJ_LINE
const SvxFrameDirectionItem & GetFrameDir(bool=true) const
Definition: frmatr.hxx:94
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:78
tools::Long GetWidth() const
Holds data used by DocxSdrExport only.
DocxExport & m_rExport
void setFlyAttrList(const rtl::Reference< sax_fastparser::FastAttributeList > &pFlyAttrList)
tools::Long GetWidth() const
SwNode & GetNode() const
Definition: ndindex.hxx:119
bool IsParagraphHasDrawing() const
const editeng::SvxBorderLine * GetRight() const
sal_Int16 GetRelationOrient() const
Definition: fmtornt.hxx:55
The class that does all the actual DOCX export-related work.
Definition: docxexport.hxx:65
sax_fastparser::FastAttributeList * getBodyPrAttrList()
Attributes of , used during DML export of text frames.
EmbeddedObjectRef * pObject
bool getParagraphSdtOpen() const
void startDMLAnchorInline(const SwFrameFormat *pFrameFormat, const Size &rSize)
UseOnPage GetUseOn() const
Definition: pagedesc.hxx:331
rtl::Reference< sax_fastparser::FastAttributeList > & getFlyFillAttrList()
void writeDiagram(const SdrObject *sdrObject, const SwFrameFormat &rFrameFormat, int nDiagramId)
Writes a diagram (smartart).
void setDMLAndVMLDrawingOpen(bool bDMLAndVMLDrawingOpen)
static bool isTextBox(const SwFrameFormat &rFrameFormat)
Is this a standalone TextFrame, or used as a TextBox of a shape?
IDocumentDrawModelAccess const & getIDocumentDrawModelAccess() const
Definition: doc.cxx:155
void writeDMLTextFrame(ww8::Frame const *pParentFrame, int nAnchorId, bool bTextBoxOnly=false)
Writes text frame in DML format.
virtual const tools::Rectangle & GetSnapRect() const
bool IsVisible() const
DstType sequenceToContainer(const css::uno::Sequence< SrcType > &i_Sequence)
bool getDMLAndVMLDrawingOpen() const
SvxShadowLocation GetLocation() const
MSO_SPT
#define X
bool getDMLTextFrameSyntax() const
const OUString & GetName() const
Definition: format.hxx:132
Degree100 & getDMLandVMLTextFrameRotation()
oox::drawingml::DrawingML * getDrawingML() const
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
static bool isTextBox(const SwFrameFormat *pFormat, sal_uInt16 nType)
Is the frame format a text box?
Degree100 m_nDMLandVMLTextFrameRotation
List of TextBoxes in this document: they are exported as part of their shape, never alone...
const Size * getFlyFrameSize() const
const SwFormatSurround & GetSurround(bool=true) const
Definition: fmtsrnd.hxx:66
bool HasTextBoxContent(sal_uInt32 nShapeType)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
DocxSdrExport(DocxExport &rExport, const sax_fastparser::FSHelperPtr &pSerializer, oox::drawingml::DrawingML *pDrawingML)
void setParagraphSdtOpen(bool bParagraphSdtOpen)
const SwFrameFormat & GetFrameFormat() const
Get the writer SwFrameFormat that this object describes.
Impl(DocxExport &rExport, sax_fastparser::FSHelperPtr pSerializer, oox::drawingml::DrawingML *pDrawingML)
virtual SdrLayerID GetInvisibleHellId() const =0
const sax_fastparser::FSHelperPtr & getSerializer() const
ShapeFlag
void setParagraphHasDrawing(bool bParagraphHasDrawing)
const Color & GetColor() const
rtl::Reference< sax_fastparser::FastAttributeList > & getTextboxAttrList()
Attributes of the next v:textbox element.
const editeng::SvxBorderLine * GetTop() const
tools::Polygon CorrectWordWrapPolygonForExport(const tools::PolyPolygon &rPolyPoly, const SwNoTextNode *pNd, bool bCorrectCrop)
Undo all scaling / move tricks of the wrap polygon done during import.
UNDERLYING_TYPE get() const
Style of a layout element.
Definition: frmfmt.hxx:58
#define SAL_MAX_INT32
rtl::Reference< sax_fastparser::FastAttributeList > m_pTextboxAttrList
void setFlyWrapAttrList(sax_fastparser::FastAttributeList *pFlyWrapAttrList)
OptionalString sType
virtual void RestoreData()
Restore what was saved in SaveData().
Definition: wrtww8.cxx:1919
const editeng::SvxBorderLine * GetLeft() const
rtl::Reference< sax_fastparser::FastAttributeList > & getFlyAttrList()
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
int i
OStringBuffer & getTextFrameStyle()
void setFlyFrameSize(const Size *pFlyFrameSize)
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
const SwPageDesc & GetPageDesc(const size_t i) const
Definition: doc.hxx:882
const SwFormatHoriOrient & GetHoriOrient(bool=true) const
Definition: fmtornt.hxx:108
const Color & GetColor() const
ExportDataSaveRestore(DocxExport &rExport, sal_uLong nStt, sal_uLong nEnd, ww8::Frame const *pParentFrame)
bool getDrawingOpen() const
FlyAnchors.
Definition: fmtanchr.hxx:34
void setSerializer(const sax_fastparser::FSHelperPtr &pSerializer)
tools::Long GetLeft() const
sal_uInt8 GetHeightPercent() const
Definition: fmtfsize.hxx:88
const ww8::Frame * m_pParentFrame
Definition: wrtww8.hxx:515
#define SAL_MIN_INT32
tools::Long Width() const
OUString GetTitle() const
bool getTextFrameSyntax() const
sal_Int16 GetHoriOrient() const
Definition: fmtornt.hxx:87
Object Value
OStringBuffer & getTextFrameStyle()
OString ConvertColor(const Color &rColor)
sal_uInt16 GetSize() const
Marks a node in the document model.
Definition: ndindex.hxx:31
void setDMLandVMLTextFrameRotation(Degree100 nDMLandVMLTextFrameRotation)
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:140
bool IsDMLAndVMLDrawingOpen() const
sal_uInt8 GetWidthPercent() const
Definition: fmtfsize.hxx:91
rtl::Reference< sax_fastparser::FastAttributeList > & getFlyFillAttrList()
std::shared_ptr< FastSerializerHelper > FSHelperPtr
void textFrameShadow(const SwFrameFormat &rFrameFormat)
Writes wp wrapper code around an SdrObject, which itself is written using drawingML syntax...
rtl::Reference< sax_fastparser::FastAttributeList > m_pFlyAttrList
void setFlyWrapAttrList(sax_fastparser::FastAttributeList *pAttrList)
const double * GetRelativeWidth() const
sax_fastparser::FSHelperPtr m_pSerializer
sal_Int16 GetRelativeWidthRelation() const
OUString GetName() const
#define Y
sax_fastparser::FastAttributeList * m_pBodyPrAttrList
virtual SdrLayerID GetHellId() const =0
sal_Int16 GetHeightPercentRelation() const
Definition: fmtfsize.hxx:89
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
void add(const FastAttributeList &)
void setParagraphSdtOpen(bool bParagraphSdtOpen)
Set if paragraph sdt open in the current drawing.
rtl::Reference< sax_fastparser::FastAttributeList > m_pDashLineStyleAttr
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:680
const SvxULSpaceItem & GetULSpace(bool=true) const
Definition: frmatr.hxx:76
void writeVMLTextFrame(ww8::Frame const *pParentFrame, bool bTextBoxOnly=false)
Writes text frame in VML format.
rtl::Reference< sax_fastparser::FastAttributeList > & getDashLineStyle()
void setBodyPrAttrList(sax_fastparser::FastAttributeList *pBodyPrAttrList)
const SvxOpaqueItem & GetOpaque(bool=true) const
Definition: frmatr.hxx:80
iterator find(const OUString &rKey)
sal_Int16 GetRelationOrient() const
Definition: fmtornt.hxx:88
unsigned char sal_uInt8
void writeDMLDrawing(const SdrObject *pSdrObject, const SwFrameFormat *pFrameFormat, int nAnchorId)
Writes a drawing as DML.
Make exporting a Writer Frame easy.
rtl::Reference< sax_fastparser::FastAttributeList > m_pFlyFillAttrList
Flag for checking drawing in a paragraph.
SwTwips GetPos() const
Definition: fmtornt.hxx:59
void writeOnlyTextOfFrame(ww8::Frame const *pParentFrame)
Writes text from Textbox for
void setTextFrameSyntax(bool bTextFrameSyntax)
void setTextboxAttrList(const rtl::Reference< sax_fastparser::FastAttributeList > &pTextboxAttrList)
const Size & GetSize() const
The Size of the contained element.
void writeBoxItemLine(const SvxBoxItem &rBox)
Writes the drawingML markup of a box item.
tools::Long Height() const
sal_Int16 GetVertOrient() const
Definition: fmtornt.hxx:54
sax_fastparser::FastAttributeList * getBodyPrAttrList() const
const SwFormatWrapInfluenceOnObjPos & GetWrapInfluenceOnObjPos(bool=true) const
void setDMLTextFrameSyntax(bool bDMLTextFrameSyntax)
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
constexpr sal_Int32 FSNS(sal_Int32 namespc, sal_Int32 element)
constexpr TypedWhichId< SwFlyFrameFormat > RES_FLYFRMFMT(154)
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
void setSerializer(const sax_fastparser::FSHelperPtr &pSerializer)
void writeVMLDrawing(const SdrObject *sdrObj, const SwFrameFormat &rFrameFormat)
Writes a drawing as VML data.
tools::Long GetHeight() const
SvxBorderLineStyle GetBorderLineStyle() const
static bool isSupportedDMLShape(const uno::Reference< drawing::XShape > &xShape)
rtl::Reference< sax_fastparser::FastAttributeList > & getTextboxAttrList()
sal_Int16 GetRelativeHeightRelation() const
#define SAL_WARN(area, stream)
virtual const tools::Rectangle & GetLogicRect() const
bool getFlyFrameGraphic() const
OStringBuffer m_aTextFrameStyle
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:137
Frame is variable in Var-direction.
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
void setDrawingOpen(bool bDrawingOpen)
void setParagraphHasDrawing(bool bParagraphHasDrawing)
const editeng::SvxBorderLine * GetBottom() const
sal_Int16 GetWidthPercentRelation() const
Definition: fmtfsize.hxx:92
const Size * getFlyFrameSize() const
When exporting fly frames, this holds the real size of the frame.
static MSO_SPT GetCustomShapeType(const css::uno::Reference< css::drawing::XShape > &rXShape, ShapeFlag &nMirrorFlags, OUString &rShapeType, bool bOOXML=false)
SdrObject * FindRealSdrObject()
Definition: atrfrm.cxx:2712
std::unique_ptr< FastAttributeList > SurroundToVMLWrap(SwFormatSurround const &rSurround)
const double * GetRelativeHeight() const
rtl::Reference< sax_fastparser::FastAttributeList > & getDashLineStyleAttr()
sal_uInt16 GetUpper() const
DocxExport & getExport() const
SwFrameSize GetHeightSizeType() const
Definition: fmtfsize.hxx:80
sal_uInt16 GetWidth() const
static OString lcl_TransparencyToDrawingMlAlpha(const Color &rColor)
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:74
EnumT GetValue() const
const SvxShadowItem & GetShadow(bool=true) const
Definition: frmatr.hxx:88