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>
35 #include <fmtpdsc.hxx>
38 
39 using namespace com::sun::star;
40 using namespace oox;
41 
42 namespace
43 {
44 uno::Sequence<beans::PropertyValue> lclGetProperty(const uno::Reference<drawing::XShape>& rShape,
45  const OUString& rPropName)
46 {
47  uno::Sequence<beans::PropertyValue> aResult;
48  uno::Reference<beans::XPropertySet> xPropertySet(rShape, uno::UNO_QUERY);
49  uno::Reference<beans::XPropertySetInfo> xPropSetInfo;
50 
51  if (!xPropertySet.is())
52  return aResult;
53 
54  xPropSetInfo = xPropertySet->getPropertySetInfo();
55  if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(rPropName))
56  {
57  xPropertySet->getPropertyValue(rPropName) >>= aResult;
58  }
59  return aResult;
60 }
61 
62 OUString lclGetAnchorIdFromGrabBag(const SdrObject* pObj)
63 {
64  OUString aResult;
65  uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pObj)->getUnoShape(),
66  uno::UNO_QUERY);
67  OUString aGrabBagName;
68  uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY);
69  if (xServiceInfo->supportsService("com.sun.star.text.TextFrame"))
70  aGrabBagName = "FrameInteropGrabBag";
71  else
72  aGrabBagName = "InteropGrabBag";
73  uno::Sequence<beans::PropertyValue> propList = lclGetProperty(xShape, aGrabBagName);
74  auto pProp
75  = std::find_if(propList.begin(), propList.end(),
76  [](const beans::PropertyValue& rProp) { return rProp.Name == "AnchorId"; });
77  if (pProp != propList.end())
78  pProp->Value >>= aResult;
79  return aResult;
80 }
81 
82 void lclMovePositionWithRotation(awt::Point& aPos, const Size& rSize, sal_Int64 nRotation)
83 {
84  // code from ImplEESdrWriter::ImplFlipBoundingBox (filter/source/msfilter/eschesdo.cxx)
85  // TODO: refactor
86 
87  if (nRotation == 0)
88  return;
89 
90  if (nRotation < 0)
91  nRotation = (36000 + nRotation) % 36000;
92  if (nRotation % 18000 == 0)
93  nRotation = 0;
94  while (nRotation > 9000)
95  nRotation = (18000 - (nRotation % 18000));
96 
97  double fVal = static_cast<double>(nRotation) * F_PI18000;
98  double fCos = cos(fVal);
99  double fSin = sin(fVal);
100 
101  double nWidthHalf = static_cast<double>(rSize.Width()) / 2;
102  double nHeightHalf = static_cast<double>(rSize.Height()) / 2;
103 
104  double nXDiff = fSin * nHeightHalf + fCos * nWidthHalf - nWidthHalf;
105  double nYDiff = fSin * nWidthHalf + fCos * nHeightHalf - nHeightHalf;
106 
107  aPos.X += nXDiff;
108  aPos.Y += nYDiff;
109 }
110 
112 bool IsAnchorTypeInsideParagraph(const ww8::Frame* pFrame)
113 {
114  const SwFormatAnchor& rAnchor = pFrame->GetFrameFormat().GetAttrSet().GetAnchor();
115  return rAnchor.GetAnchorId() != RndStdIds::FLY_AT_PAGE;
116 }
117 }
118 
120  ww8::Frame const* pParentFrame)
121  : m_rExport(rExport)
122 {
123  m_rExport.SaveData(nStt, nEnd);
124  m_rExport.m_pParentFrame = pParentFrame;
125 }
126 
128 
131 {
132 private:
141  OStringBuffer m_aTextFrameStyle;
153 
154 public:
155  bool m_bFlyFrameGraphic = false;
156 
158  oox::drawingml::DrawingML* pDrawingML)
159  : m_rExport(rExport)
160  , m_pSerializer(std::move(pSerializer))
161  , m_pDrawingML(pDrawingML)
162  , m_pFlyFrameSize(nullptr)
163  , m_bTextFrameSyntax(false)
164  , m_bDMLTextFrameSyntax(false)
165  , m_bDrawingOpen(false)
166  , m_bParagraphSdtOpen(false)
167  , m_bParagraphHasDrawing(false)
168  , m_pFlyWrapAttrList(nullptr)
169  , m_pBodyPrAttrList(nullptr)
170  , m_bDMLAndVMLDrawingOpen(false)
171  , m_nDMLandVMLTextFrameRotation(0)
172  {
173  }
174 
176 
177  void textFrameShadow(const SwFrameFormat& rFrameFormat);
178  static bool isSupportedDMLShape(const uno::Reference<drawing::XShape>& xShape);
179 
181  {
182  m_pSerializer = pSerializer;
183  }
184 
186 
187  void setFlyFrameSize(const Size* pFlyFrameSize) { m_pFlyFrameSize = pFlyFrameSize; }
188 
189  const Size* getFlyFrameSize() const { return m_pFlyFrameSize; }
190 
191  void setTextFrameSyntax(bool bTextFrameSyntax) { m_bTextFrameSyntax = bTextFrameSyntax; }
192 
193  bool getTextFrameSyntax() const { return m_bTextFrameSyntax; }
194 
195  void setDMLTextFrameSyntax(bool bDMLTextFrameSyntax)
196  {
197  m_bDMLTextFrameSyntax = bDMLTextFrameSyntax;
198  }
199 
201 
203  {
204  m_pFlyAttrList = pFlyAttrList;
205  }
206 
208 
209  void
211  {
212  m_pTextboxAttrList = pTextboxAttrList;
213  }
214 
216  {
217  return m_pTextboxAttrList;
218  }
219 
220  OStringBuffer& getTextFrameStyle() { return m_aTextFrameStyle; }
221 
222  void setDrawingOpen(bool bDrawingOpen) { m_bDrawingOpen = bDrawingOpen; }
223 
224  bool getDrawingOpen() const { return m_bDrawingOpen; }
225 
226  void setParagraphSdtOpen(bool bParagraphSdtOpen) { m_bParagraphSdtOpen = bParagraphSdtOpen; }
227 
228  bool getParagraphSdtOpen() const { return m_bParagraphSdtOpen; }
229 
230  void setDMLAndVMLDrawingOpen(bool bDMLAndVMLDrawingOpen)
231  {
232  m_bDMLAndVMLDrawingOpen = bDMLAndVMLDrawingOpen;
233  }
234 
236 
237  void setParagraphHasDrawing(bool bParagraphHasDrawing)
238  {
239  m_bParagraphHasDrawing = bParagraphHasDrawing;
240  }
241 
243 
245  {
246  return m_pFlyFillAttrList;
247  }
248 
250  {
251  m_pFlyWrapAttrList = pFlyWrapAttrList;
252  }
253 
255 
257  {
258  m_pBodyPrAttrList = pBodyPrAttrList;
259  }
260 
262 
264  {
265  return m_pDashLineStyleAttr;
266  }
267 
268  bool getFlyFrameGraphic() const { return m_bFlyFrameGraphic; }
269 
271 
272  DocxExport& getExport() const { return m_rExport; }
273 
274  void setDMLandVMLTextFrameRotation(sal_Int32 nDMLandVMLTextFrameRotation)
275  {
276  m_nDMLandVMLTextFrameRotation = nDMLandVMLTextFrameRotation;
277  }
278 
280 };
281 
283  oox::drawingml::DrawingML* pDrawingML)
284  : m_pImpl(std::make_unique<Impl>(rExport, pSerializer, pDrawingML))
285 {
286 }
287 
289 
291 {
292  m_pImpl->setSerializer(pSerializer);
293 }
294 
295 const Size* DocxSdrExport::getFlyFrameSize() const { return m_pImpl->getFlyFrameSize(); }
296 
297 bool DocxSdrExport::getTextFrameSyntax() const { return m_pImpl->getTextFrameSyntax(); }
298 
299 bool DocxSdrExport::getDMLTextFrameSyntax() const { return m_pImpl->getDMLTextFrameSyntax(); }
300 
302 {
303  return m_pImpl->getFlyAttrList();
304 }
305 
307 {
308  return m_pImpl->getTextboxAttrList();
309 }
310 
311 OStringBuffer& DocxSdrExport::getTextFrameStyle() { return m_pImpl->getTextFrameStyle(); }
312 
313 bool DocxSdrExport::IsDrawingOpen() const { return m_pImpl->getDrawingOpen(); }
314 
315 void DocxSdrExport::setParagraphSdtOpen(bool bParagraphSdtOpen)
316 {
317  m_pImpl->setParagraphSdtOpen(bParagraphSdtOpen);
318 }
319 
320 bool DocxSdrExport::IsDMLAndVMLDrawingOpen() const { return m_pImpl->getDMLAndVMLDrawingOpen(); }
321 
322 bool DocxSdrExport::IsParagraphHasDrawing() const { return m_pImpl->getParagraphHasDrawing(); }
323 
324 void DocxSdrExport::setParagraphHasDrawing(bool bParagraphHasDrawing)
325 {
326  m_pImpl->setParagraphHasDrawing(bParagraphHasDrawing);
327 }
328 
330 {
331  return m_pImpl->getFlyFillAttrList();
332 }
333 
335 {
336  return m_pImpl->getBodyPrAttrList();
337 }
338 
340 {
341  return m_pImpl->getDashLineStyleAttr();
342 }
343 
345 {
346  m_pImpl->setFlyWrapAttrList(pAttrList);
347 }
348 
349 void DocxSdrExport::startDMLAnchorInline(const SwFrameFormat* pFrameFormat, const Size& rSize)
350 {
351  m_pImpl->setDrawingOpen(true);
352  m_pImpl->setParagraphHasDrawing(true);
353  m_pImpl->getSerializer()->startElementNS(XML_w, XML_drawing);
354 
355  // tdf#135047: It must be allowed to find in parents too, but default value of bInP parameter
356  // for GetLRSpace() and GetULSpace() is true, so no direct setting is required.
357  const SvxLRSpaceItem& aLRSpaceItem = pFrameFormat->GetLRSpace();
358  const SvxULSpaceItem& aULSpaceItem = pFrameFormat->GetULSpace();
359 
360  bool isAnchor;
361 
362  if (m_pImpl->getFlyFrameGraphic())
363  {
364  isAnchor = false; // make Graphic object inside DMLTextFrame & VMLTextFrame as Inline
365  }
366  else
367  {
368  isAnchor = pFrameFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR;
369  }
370 
371  // Count effectExtent values, their value is needed before dist{T,B,L,R} is written.
372  SvxShadowItem aShadowItem = pFrameFormat->GetShadow();
373  sal_Int32 nLeftExt = 0;
374  sal_Int32 nRightExt = 0;
375  sal_Int32 nTopExt = 0;
376  sal_Int32 nBottomExt = 0;
377  if (aShadowItem.GetLocation() != SvxShadowLocation::NONE)
378  {
379  sal_Int32 nShadowWidth(TwipsToEMU(aShadowItem.GetWidth()));
380  switch (aShadowItem.GetLocation())
381  {
382  case SvxShadowLocation::TopLeft:
383  nTopExt = nLeftExt = nShadowWidth;
384  break;
385  case SvxShadowLocation::TopRight:
386  nTopExt = nRightExt = nShadowWidth;
387  break;
388  case SvxShadowLocation::BottomLeft:
389  nBottomExt = nLeftExt = nShadowWidth;
390  break;
391  case SvxShadowLocation::BottomRight:
392  nBottomExt = nRightExt = nShadowWidth;
393  break;
394  case SvxShadowLocation::NONE:
395  case SvxShadowLocation::End:
396  break;
397  }
398  }
399  else if (const SdrObject* pObject = pFrameFormat->FindRealSdrObject())
400  {
401  // No shadow, but we have an idea what was the original effectExtent.
402  uno::Any aAny;
403  pObject->GetGrabBagItem(aAny);
404  comphelper::SequenceAsHashMap aGrabBag(aAny);
405  auto it = aGrabBag.find("CT_EffectExtent");
406  if (it != aGrabBag.end())
407  {
408  comphelper::SequenceAsHashMap aEffectExtent(it->second);
409  for (const std::pair<const OUString, uno::Any>& rDirection : aEffectExtent)
410  {
411  if (rDirection.first == "l" && rDirection.second.has<sal_Int32>())
412  nLeftExt = rDirection.second.get<sal_Int32>();
413  else if (rDirection.first == "t" && rDirection.second.has<sal_Int32>())
414  nTopExt = rDirection.second.get<sal_Int32>();
415  else if (rDirection.first == "r" && rDirection.second.has<sal_Int32>())
416  nRightExt = rDirection.second.get<sal_Int32>();
417  else if (rDirection.first == "b" && rDirection.second.has<sal_Int32>())
418  nBottomExt = rDirection.second.get<sal_Int32>();
419  }
420  }
421  }
422 
423  if (isAnchor)
424  {
427  bool bOpaque = pFrameFormat->GetOpaque().GetValue();
428  awt::Point aPos(pFrameFormat->GetHoriOrient().GetPos(),
429  pFrameFormat->GetVertOrient().GetPos());
430  const SdrObject* pObj = pFrameFormat->FindRealSdrObject();
431  tools::Long nRotation = 0;
432  if (pObj != nullptr)
433  {
434  // SdrObjects know their layer, consider that instead of the frame format.
435  bOpaque = pObj->GetLayer()
436  != pFrameFormat->GetDoc()->getIDocumentDrawModelAccess().GetHellId()
437  && pObj->GetLayer()
438  != pFrameFormat->GetDoc()
441 
442  // Do not do this with lines.
443  if (pObj->GetObjIdentifier() != OBJ_LINE)
444  {
445  nRotation = pObj->GetRotateAngle();
446  lclMovePositionWithRotation(aPos, rSize, nRotation);
447  }
448  }
449  attrList->add(XML_behindDoc, bOpaque ? "0" : "1");
450  // Extend distance with the effect extent if the shape is not rotated, which is the opposite
451  // of the mapping done at import time.
452  // The type of dist* attributes is unsigned, so make sure no negative value is written.
453  sal_Int64 nTopExtDist = nRotation ? 0 : nTopExt;
454  sal_Int64 nDistT = std::max(static_cast<sal_Int64>(0),
455  TwipsToEMU(aULSpaceItem.GetUpper()) - nTopExtDist);
456  attrList->add(XML_distT, OString::number(nDistT).getStr());
457  sal_Int64 nBottomExtDist = nRotation ? 0 : nBottomExt;
458  sal_Int64 nDistB = std::max(static_cast<sal_Int64>(0),
459  TwipsToEMU(aULSpaceItem.GetLower()) - nBottomExtDist);
460  attrList->add(XML_distB, OString::number(nDistB).getStr());
461  sal_Int64 nLeftExtDist = nRotation ? 0 : nLeftExt;
462  sal_Int64 nDistL = std::max(static_cast<sal_Int64>(0),
463  TwipsToEMU(aLRSpaceItem.GetLeft()) - nLeftExtDist);
464  attrList->add(XML_distL, OString::number(nDistL).getStr());
465  sal_Int64 nRightExtDist = nRotation ? 0 : nRightExt;
466  sal_Int64 nDistR = std::max(static_cast<sal_Int64>(0),
467  TwipsToEMU(aLRSpaceItem.GetRight()) - nRightExtDist);
468  attrList->add(XML_distR, OString::number(nDistR).getStr());
469  attrList->add(XML_simplePos, "0");
470  attrList->add(XML_locked, "0");
471  bool bLclInTabCell = true;
472  if (pObj)
473  {
474  uno::Reference<drawing::XShape> xShape((const_cast<SdrObject*>(pObj)->getUnoShape()),
475  uno::UNO_QUERY);
476  uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
477  if (xShapeProps.is())
478  xShapeProps->getPropertyValue("IsFollowingTextFlow") >>= bLclInTabCell;
479  }
480  if (bLclInTabCell)
481  attrList->add(XML_layoutInCell, "1");
482  else
483  attrList->add(XML_layoutInCell, "0");
484  bool bAllowOverlap = pFrameFormat->GetWrapInfluenceOnObjPos().GetAllowOverlap();
485  attrList->add(XML_allowOverlap, bAllowOverlap ? "1" : "0");
486  if (pObj != nullptr)
487  // It seems 0 and 1 have special meaning: just start counting from 2 to avoid issues with that.
488  attrList->add(XML_relativeHeight, OString::number(pObj->GetOrdNum() + 2));
489  else
490  // relativeHeight is mandatory attribute, if value is not present, we must write default value
491  attrList->add(XML_relativeHeight, "0");
492  if (pObj != nullptr)
493  {
494  OUString sAnchorId = lclGetAnchorIdFromGrabBag(pObj);
495  if (!sAnchorId.isEmpty())
496  attrList->addNS(XML_wp14, XML_anchorId,
497  OUStringToOString(sAnchorId, RTL_TEXTENCODING_UTF8));
498  }
499  sax_fastparser::XFastAttributeListRef xAttrList(attrList);
500  m_pImpl->getSerializer()->startElementNS(XML_wp, XML_anchor, xAttrList);
501  m_pImpl->getSerializer()->singleElementNS(XML_wp, XML_simplePos, XML_x, "0", XML_y,
502  "0"); // required, unused
503  const char* relativeFromH;
504  const char* relativeFromV;
505  const char* alignH = nullptr;
506  const char* alignV = nullptr;
507  switch (pFrameFormat->GetVertOrient().GetRelationOrient())
508  {
509  case text::RelOrientation::PAGE_PRINT_AREA:
510  relativeFromV = "margin";
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 = TwipsToEMU(std::clamp(rSize.Width(), 0L, tools::Long(SAL_MAX_INT32)));
717  OString aWidth(OString::number(std::min(cx, sal_uInt64(SAL_MAX_INT32))));
718  sal_uInt64 cy = TwipsToEMU(std::clamp(rSize.Height(), 0L, tools::Long(SAL_MAX_INT32)));
719  OString aHeight(OString::number(std::min(cy, sal_uInt64(SAL_MAX_INT32))));
720 
721  m_pImpl->getSerializer()->singleElementNS(XML_wp, XML_extent, XML_cx, aWidth, XML_cy, aHeight);
722 
723  // effectExtent, extent including the effect (shadow only for now)
724  m_pImpl->getSerializer()->singleElementNS(
725  XML_wp, XML_effectExtent, XML_l, OString::number(nLeftExt), XML_t, OString::number(nTopExt),
726  XML_r, OString::number(nRightExt), XML_b, OString::number(nBottomExt));
727 
728  // See if we know the exact wrap type from grab-bag.
729  sal_Int32 nWrapToken = 0;
730  if (const SdrObject* pObject = pFrameFormat->FindRealSdrObject())
731  {
732  uno::Any aAny;
733  pObject->GetGrabBagItem(aAny);
734  comphelper::SequenceAsHashMap aGrabBag(aAny);
735  auto it = aGrabBag.find("EG_WrapType");
736  if (it != aGrabBag.end())
737  {
738  auto sType = it->second.get<OUString>();
739  if (sType == "wrapTight")
740  nWrapToken = XML_wrapTight;
741  else if (sType == "wrapThrough")
742  nWrapToken = XML_wrapThrough;
743  else
744  SAL_WARN("sw.ww8",
745  "DocxSdrExport::startDMLAnchorInline: unexpected EG_WrapType value");
746 
747  m_pImpl->getSerializer()->startElementNS(XML_wp, nWrapToken, XML_wrapText, "bothSides");
748 
749  it = aGrabBag.find("CT_WrapPath");
750  if (it != aGrabBag.end())
751  {
752  m_pImpl->getSerializer()->startElementNS(XML_wp, XML_wrapPolygon, XML_edited, "0");
753  auto aSeqSeq = it->second.get<drawing::PointSequenceSequence>();
754  auto aPoints(comphelper::sequenceToContainer<std::vector<awt::Point>>(aSeqSeq[0]));
755  for (auto i = aPoints.begin(); i != aPoints.end(); ++i)
756  {
757  awt::Point& rPoint = *i;
758  m_pImpl->getSerializer()->singleElementNS(
759  XML_wp, (i == aPoints.begin() ? XML_start : XML_lineTo), XML_x,
760  OString::number(rPoint.X), XML_y, OString::number(rPoint.Y));
761  }
762  m_pImpl->getSerializer()->endElementNS(XML_wp, XML_wrapPolygon);
763  }
764 
765  m_pImpl->getSerializer()->endElementNS(XML_wp, nWrapToken);
766  }
767  }
768 
769  // Or if we have a contour.
770  if (!nWrapToken && pFrameFormat->GetSurround().IsContour())
771  {
772  if (const SwNoTextNode* pNd = sw::util::GetNoTextNodeFromSwFrameFormat(*pFrameFormat))
773  {
774  const tools::PolyPolygon* pPolyPoly = pNd->HasContour();
775  if (pPolyPoly && pPolyPoly->Count())
776  {
777  nWrapToken = XML_wrapTight;
778  m_pImpl->getSerializer()->startElementNS(XML_wp, nWrapToken, XML_wrapText,
779  "bothSides");
780 
781  m_pImpl->getSerializer()->startElementNS(XML_wp, XML_wrapPolygon, XML_edited, "0");
783  *pPolyPoly, pNd, /*bCorrectCrop=*/true);
784  for (sal_uInt16 i = 0; i < aPoly.GetSize(); ++i)
785  m_pImpl->getSerializer()->singleElementNS(
786  XML_wp, (i == 0 ? XML_start : XML_lineTo), XML_x,
787  OString::number(aPoly[i].X()), XML_y, OString::number(aPoly[i].Y()));
788  m_pImpl->getSerializer()->endElementNS(XML_wp, XML_wrapPolygon);
789 
790  m_pImpl->getSerializer()->endElementNS(XML_wp, nWrapToken);
791  }
792  }
793  }
794 
795  // No? Then just approximate based on what we have.
796  if (!isAnchor || nWrapToken)
797  return;
798 
799  switch (pFrameFormat->GetSurround().GetValue())
800  {
801  case css::text::WrapTextMode_NONE:
802  m_pImpl->getSerializer()->singleElementNS(XML_wp, XML_wrapTopAndBottom);
803  break;
804  case css::text::WrapTextMode_THROUGH:
805  m_pImpl->getSerializer()->singleElementNS(XML_wp, XML_wrapNone);
806  break;
807  case css::text::WrapTextMode_PARALLEL:
808  m_pImpl->getSerializer()->singleElementNS(XML_wp, XML_wrapSquare, XML_wrapText,
809  "bothSides");
810  break;
811  case css::text::WrapTextMode_DYNAMIC:
812  default:
813  m_pImpl->getSerializer()->singleElementNS(XML_wp, XML_wrapSquare, XML_wrapText,
814  "largest");
815  break;
816  }
817 }
818 
820 {
821  bool isAnchor;
822  if (m_pImpl->getFlyFrameGraphic())
823  {
824  isAnchor = false; // end Inline Graphic object inside DMLTextFrame
825  }
826  else
827  {
828  isAnchor = pFrameFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR;
829  }
830  m_pImpl->getSerializer()->endElementNS(XML_wp, isAnchor ? XML_anchor : XML_inline);
831 
832  m_pImpl->getSerializer()->endElementNS(XML_w, XML_drawing);
833  m_pImpl->setDrawingOpen(false);
834 }
835 
836 void DocxSdrExport::writeVMLDrawing(const SdrObject* sdrObj, const SwFrameFormat& rFrameFormat)
837 {
838  m_pImpl->getSerializer()->startElementNS(XML_w, XML_pict);
839  m_pImpl->getDrawingML()->SetFS(m_pImpl->getSerializer());
840  // See WinwordAnchoring::SetAnchoring(), these are not part of the SdrObject, have to be passed around manually.
841 
842  const SwFormatHoriOrient& rHoriOri = rFrameFormat.GetHoriOrient();
843  const SwFormatVertOrient& rVertOri = rFrameFormat.GetVertOrient();
844  SwFormatSurround const& rSurround(rFrameFormat.GetSurround());
845 
846  std::unique_ptr<sax_fastparser::FastAttributeList> pAttrList(
847  docx::SurroundToVMLWrap(rSurround));
848  m_pImpl->getExport().VMLExporter().AddSdrObject(
849  *sdrObj, rHoriOri.GetHoriOrient(), rVertOri.GetVertOrient(), rHoriOri.GetRelationOrient(),
850  rVertOri.GetRelationOrient(), std::move(pAttrList), true);
851  m_pImpl->getSerializer()->endElementNS(XML_w, XML_pict);
852 }
853 
854 static bool lcl_isLockedCanvas(const uno::Reference<drawing::XShape>& xShape)
855 {
856  uno::Sequence<beans::PropertyValue> propList = lclGetProperty(xShape, "InteropGrabBag");
857  /*
858  * Export as Locked Canvas only if the property
859  * is in the PropertySet
860  */
861  return std::any_of(propList.begin(), propList.end(), [](const beans::PropertyValue& rProp) {
862  return rProp.Name == "LockedCanvas";
863  });
864 }
865 
866 void DocxSdrExport::writeDMLDrawing(const SdrObject* pSdrObject, const SwFrameFormat* pFrameFormat,
867  int nAnchorId)
868 {
869  uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pSdrObject)->getUnoShape(),
870  uno::UNO_QUERY_THROW);
871  if (!Impl::isSupportedDMLShape(xShape))
872  return;
873 
874  m_pImpl->getExport().DocxAttrOutput().GetSdtEndBefore(pSdrObject);
875 
876  sax_fastparser::FSHelperPtr pFS = m_pImpl->getSerializer();
877  Size aSize(pSdrObject->GetLogicRect().GetWidth(), pSdrObject->GetLogicRect().GetHeight());
878  startDMLAnchorInline(pFrameFormat, aSize);
879 
880  sax_fastparser::FastAttributeList* pDocPrAttrList
882  pDocPrAttrList->add(XML_id, OString::number(nAnchorId).getStr());
883  pDocPrAttrList->add(XML_name,
884  OUStringToOString(pSdrObject->GetName(), RTL_TEXTENCODING_UTF8).getStr());
885  if (!pSdrObject->GetTitle().isEmpty())
886  pDocPrAttrList->add(XML_title,
887  OUStringToOString(pSdrObject->GetTitle(), RTL_TEXTENCODING_UTF8));
888  if (!pSdrObject->GetDescription().isEmpty())
889  pDocPrAttrList->add(XML_descr,
890  OUStringToOString(pSdrObject->GetDescription(), RTL_TEXTENCODING_UTF8));
891  if (!pSdrObject->IsVisible()
892  && pFrameFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR)
893 
894  pDocPrAttrList->add(XML_hidden, OString::number(1).getStr());
895  sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList);
896  pFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef);
897 
898  uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY_THROW);
899  const char* pNamespace = "http://schemas.microsoft.com/office/word/2010/wordprocessingShape";
900  if (xServiceInfo->supportsService("com.sun.star.drawing.GroupShape"))
901  pNamespace = "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup";
902  else if (xServiceInfo->supportsService("com.sun.star.drawing.GraphicObjectShape"))
903  pNamespace = "http://schemas.openxmlformats.org/drawingml/2006/picture";
904  pFS->startElementNS(XML_a, XML_graphic, FSNS(XML_xmlns, XML_a),
905  m_pImpl->getExport().GetFilter().getNamespaceURL(OOX_NS(dml)));
906  pFS->startElementNS(XML_a, XML_graphicData, XML_uri, pNamespace);
907 
908  bool bLockedCanvas = lcl_isLockedCanvas(xShape);
909  if (bLockedCanvas)
910  pFS->startElementNS(
911  XML_lc, XML_lockedCanvas, FSNS(XML_xmlns, XML_lc),
912  m_pImpl->getExport().GetFilter().getNamespaceURL(OOX_NS(dmlLockedCanvas)));
913 
914  m_pImpl->getExport().OutputDML(xShape);
915 
916  if (bLockedCanvas)
917  pFS->endElementNS(XML_lc, XML_lockedCanvas);
918  pFS->endElementNS(XML_a, XML_graphicData);
919  pFS->endElementNS(XML_a, XML_graphic);
920 
921  // Relative size of the drawing.
922  if (pSdrObject->GetRelativeWidth())
923  {
924  // At the moment drawinglayer objects are always relative from page.
925  OUString sValue;
926  switch (pSdrObject->GetRelativeWidthRelation())
927  {
928  case text::RelOrientation::FRAME:
929  sValue = "margin";
930  break;
931  case text::RelOrientation::PAGE_LEFT:
932  if (pFrameFormat->GetDoc()->GetPageDesc(0).GetUseOn() == UseOnPage::Mirror)
933  sValue = "outsideMargin";
934  else
935  sValue = "leftMargin";
936  break;
937  case text::RelOrientation::PAGE_RIGHT:
938  if (pFrameFormat->GetDoc()->GetPageDesc(0).GetUseOn() == UseOnPage::Mirror)
939  sValue = "insideMargin";
940  else
941  sValue = "rightMargin";
942  break;
943  case text::RelOrientation::PAGE_FRAME:
944  default:
945  sValue = "page";
946  break;
947  }
948  pFS->startElementNS(XML_wp14, XML_sizeRelH, XML_relativeFrom, sValue);
949  pFS->startElementNS(XML_wp14, XML_pctWidth);
950  pFS->writeEscaped(
951  OUString::number(*pSdrObject->GetRelativeWidth() * 100 * oox::drawingml::PER_PERCENT));
952  pFS->endElementNS(XML_wp14, XML_pctWidth);
953  pFS->endElementNS(XML_wp14, XML_sizeRelH);
954  }
955  if (pSdrObject->GetRelativeHeight())
956  {
957  OUString sValue;
958  switch (pSdrObject->GetRelativeHeightRelation())
959  {
960  case text::RelOrientation::FRAME:
961  sValue = "margin";
962  break;
963  case text::RelOrientation::PAGE_PRINT_AREA:
964  sValue = "topMargin";
965  break;
966  case text::RelOrientation::PAGE_PRINT_AREA_BOTTOM:
967  sValue = "bottomMargin";
968  break;
969  case text::RelOrientation::PAGE_FRAME:
970  default:
971  sValue = "page";
972  break;
973  }
974  pFS->startElementNS(XML_wp14, XML_sizeRelV, XML_relativeFrom, sValue);
975  pFS->startElementNS(XML_wp14, XML_pctHeight);
976  pFS->writeEscaped(
977  OUString::number(*pSdrObject->GetRelativeHeight() * 100 * oox::drawingml::PER_PERCENT));
978  pFS->endElementNS(XML_wp14, XML_pctHeight);
979  pFS->endElementNS(XML_wp14, XML_sizeRelV);
980  }
981 
982  endDMLAnchorInline(pFrameFormat);
983 }
984 
986 {
987  const SvxShadowItem& aShadowItem = rFrameFormat.GetShadow();
988  if (aShadowItem.GetLocation() == SvxShadowLocation::NONE)
989  return;
990 
991  OString aShadowWidth(OString::number(double(aShadowItem.GetWidth()) / 20) + "pt");
992  OString aOffset;
993  switch (aShadowItem.GetLocation())
994  {
995  case SvxShadowLocation::TopLeft:
996  aOffset = "-" + aShadowWidth + ",-" + aShadowWidth;
997  break;
998  case SvxShadowLocation::TopRight:
999  aOffset = aShadowWidth + ",-" + aShadowWidth;
1000  break;
1001  case SvxShadowLocation::BottomLeft:
1002  aOffset = "-" + aShadowWidth + "," + aShadowWidth;
1003  break;
1004  case SvxShadowLocation::BottomRight:
1005  aOffset = aShadowWidth + "," + aShadowWidth;
1006  break;
1007  case SvxShadowLocation::NONE:
1008  case SvxShadowLocation::End:
1009  break;
1010  }
1011  if (aOffset.isEmpty())
1012  return;
1013 
1014  OString aShadowColor = msfilter::util::ConvertColor(aShadowItem.GetColor());
1015  m_pSerializer->singleElementNS(XML_v, XML_shadow, XML_on, "t", XML_color, "#" + aShadowColor,
1016  XML_offset, aOffset);
1017 }
1018 
1019 bool DocxSdrExport::Impl::isSupportedDMLShape(const uno::Reference<drawing::XShape>& xShape)
1020 {
1021  uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY_THROW);
1022  if (xServiceInfo->supportsService("com.sun.star.drawing.PolyPolygonShape")
1023  || xServiceInfo->supportsService("com.sun.star.drawing.PolyLineShape"))
1024  return false;
1025 
1026  // For signature line shapes, we don't want DML, just the VML shape.
1027  if (xServiceInfo->supportsService("com.sun.star.drawing.GraphicObjectShape"))
1028  {
1029  uno::Reference<beans::XPropertySet> xShapeProperties(xShape, uno::UNO_QUERY);
1030  bool bIsSignatureLineShape = false;
1031  xShapeProperties->getPropertyValue("IsSignatureLine") >>= bIsSignatureLineShape;
1032  if (bIsSignatureLineShape)
1033  return false;
1034  }
1035 
1036  return true;
1037 }
1038 
1040  const SwFrameFormat& rFrameFormat, int nAnchorId)
1041 {
1042  bool bDMLAndVMLDrawingOpen = m_pImpl->getDMLAndVMLDrawingOpen();
1043  m_pImpl->setDMLAndVMLDrawingOpen(true);
1044 
1045  // Depending on the shape type, we actually don't write the shape as DML.
1046  OUString sShapeType;
1047  ShapeFlag nMirrorFlags = ShapeFlag::NONE;
1048  uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(sdrObj)->getUnoShape(),
1049  uno::UNO_QUERY_THROW);
1050 
1051  MSO_SPT eShapeType
1052  = EscherPropertyContainer::GetCustomShapeType(xShape, nMirrorFlags, sShapeType);
1053 
1054  // In case we are already inside a DML block, then write the shape only as VML, turn out that's allowed to do.
1055  // A common service created in util to check for VML shapes which are allowed to have textbox in content
1057  && (!bDMLAndVMLDrawingOpen || lcl_isLockedCanvas(xShape))) // Locked canvas is OK inside DML
1058  {
1059  m_pImpl->getSerializer()->startElementNS(XML_mc, XML_AlternateContent);
1060 
1061  auto pObjGroup = dynamic_cast<const SdrObjGroup*>(sdrObj);
1062  m_pImpl->getSerializer()->startElementNS(XML_mc, XML_Choice, XML_Requires,
1063  (pObjGroup ? "wpg" : "wps"));
1064  writeDMLDrawing(sdrObj, &rFrameFormat, nAnchorId);
1065  m_pImpl->getSerializer()->endElementNS(XML_mc, XML_Choice);
1066 
1067  m_pImpl->getSerializer()->startElementNS(XML_mc, XML_Fallback);
1068  writeVMLDrawing(sdrObj, rFrameFormat);
1069  m_pImpl->getSerializer()->endElementNS(XML_mc, XML_Fallback);
1070 
1071  m_pImpl->getSerializer()->endElementNS(XML_mc, XML_AlternateContent);
1072  }
1073  else
1074  writeVMLDrawing(sdrObj, rFrameFormat);
1075 
1076  m_pImpl->setDMLAndVMLDrawingOpen(bDMLAndVMLDrawingOpen);
1077 }
1078 
1079 // Converts ARGB transparency (0..255) to drawingml alpha (opposite, and 0..100000)
1080 static OString lcl_ConvertTransparency(const Color& rColor)
1081 {
1082  if (rColor.GetTransparency() > 0)
1083  {
1084  sal_Int32 nTransparencyPercent = 100 - float(rColor.GetTransparency()) / 2.55;
1085  return OString::number(nTransparencyPercent * oox::drawingml::PER_PERCENT);
1086  }
1087 
1088  return OString();
1089 }
1090 
1092 {
1093  const SvxShadowItem& aShadowItem = rFrameFormat.GetShadow();
1094 
1095  // Output effects
1096  if (aShadowItem.GetLocation() == SvxShadowLocation::NONE)
1097  return;
1098 
1099  // Distance is measured diagonally from corner
1100  double nShadowDist
1101  = sqrt(static_cast<double>(aShadowItem.GetWidth()) * aShadowItem.GetWidth() * 2.0);
1102  OString aShadowDist(OString::number(TwipsToEMU(nShadowDist)));
1103  OString aShadowColor = msfilter::util::ConvertColor(aShadowItem.GetColor());
1104  OString aShadowAlpha = lcl_ConvertTransparency(aShadowItem.GetColor());
1105  sal_uInt32 nShadowDir = 0;
1106  switch (aShadowItem.GetLocation())
1107  {
1108  case SvxShadowLocation::TopLeft:
1109  nShadowDir = 13500000;
1110  break;
1111  case SvxShadowLocation::TopRight:
1112  nShadowDir = 18900000;
1113  break;
1114  case SvxShadowLocation::BottomLeft:
1115  nShadowDir = 8100000;
1116  break;
1117  case SvxShadowLocation::BottomRight:
1118  nShadowDir = 2700000;
1119  break;
1120  case SvxShadowLocation::NONE:
1121  case SvxShadowLocation::End:
1122  break;
1123  }
1124  OString aShadowDir(OString::number(nShadowDir));
1125 
1126  m_pImpl->getSerializer()->startElementNS(XML_a, XML_effectLst);
1127  m_pImpl->getSerializer()->startElementNS(XML_a, XML_outerShdw, XML_dist, aShadowDist, XML_dir,
1128  aShadowDir);
1129  if (aShadowAlpha.isEmpty())
1130  m_pImpl->getSerializer()->singleElementNS(XML_a, XML_srgbClr, XML_val, aShadowColor);
1131  else
1132  {
1133  m_pImpl->getSerializer()->startElementNS(XML_a, XML_srgbClr, XML_val, aShadowColor);
1134  m_pImpl->getSerializer()->singleElementNS(XML_a, XML_alpha, XML_val, aShadowAlpha);
1135  m_pImpl->getSerializer()->endElementNS(XML_a, XML_srgbClr);
1136  }
1137  m_pImpl->getSerializer()->endElementNS(XML_a, XML_outerShdw);
1138  m_pImpl->getSerializer()->endElementNS(XML_a, XML_effectLst);
1139 }
1140 
1141 void DocxSdrExport::writeDiagram(const SdrObject* sdrObject, const SwFrameFormat& rFrameFormat,
1142  int nDiagramId)
1143 {
1144  uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(sdrObject)->getUnoShape(),
1145  uno::UNO_QUERY);
1146 
1147  // write necessary tags to document.xml
1148  Size aSize(sdrObject->GetSnapRect().GetWidth(), sdrObject->GetSnapRect().GetHeight());
1149  startDMLAnchorInline(&rFrameFormat, aSize);
1150 
1151  m_pImpl->getDrawingML()->WriteDiagram(xShape, nDiagramId);
1152 
1153  endDMLAnchorInline(&rFrameFormat);
1154 }
1155 
1157 {
1158  const SwFrameFormat& rFrameFormat = pParentFrame->GetFrameFormat();
1159  const SwNodeIndex* pNodeIndex = rFrameFormat.GetContent().GetContentIdx();
1160 
1161  sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex() + 1 : 0;
1162  sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1163 
1164  //Save data here and restore when out of scope
1165  ExportDataSaveRestore aDataGuard(m_pImpl->getExport(), nStt, nEnd, pParentFrame);
1166 
1168  ::comphelper::FlagRestorationGuard const g(m_pImpl->m_bFlyFrameGraphic, true);
1169  comphelper::ValueRestorationGuard vg(m_pImpl->getExport().m_nTextTyp, TXT_TXTBOX);
1170  m_pImpl->getExport().WriteText();
1171 }
1172 
1174 {
1175  const editeng::SvxBorderLine* pBorderLine = nullptr;
1176 
1177  if (rBox.GetTop())
1178  {
1179  pBorderLine = rBox.GetTop();
1180  }
1181  else if (rBox.GetLeft())
1182  {
1183  pBorderLine = rBox.GetLeft();
1184  }
1185  else if (rBox.GetBottom())
1186  {
1187  pBorderLine = rBox.GetBottom();
1188  }
1189  else if (rBox.GetRight())
1190  {
1191  pBorderLine = rBox.GetRight();
1192  }
1193 
1194  if (!pBorderLine)
1195  {
1196  return;
1197  }
1198 
1199  sax_fastparser::FSHelperPtr pFS = m_pImpl->getSerializer();
1200  double fConverted(editeng::ConvertBorderWidthToWord(pBorderLine->GetBorderLineStyle(),
1201  pBorderLine->GetWidth()));
1202  OString sWidth(OString::number(TwipsToEMU(fConverted)));
1203  pFS->startElementNS(XML_a, XML_ln, XML_w, sWidth);
1204 
1205  pFS->startElementNS(XML_a, XML_solidFill);
1206  OString sColor(msfilter::util::ConvertColor(pBorderLine->GetColor()));
1207  pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, sColor);
1208  pFS->endElementNS(XML_a, XML_solidFill);
1209 
1210  if (SvxBorderLineStyle::DASHED == pBorderLine->GetBorderLineStyle()) // Line Style is Dash type
1211  pFS->singleElementNS(XML_a, XML_prstDash, XML_val, "dash");
1212 
1213  pFS->endElementNS(XML_a, XML_ln);
1214 }
1215 
1216 void DocxSdrExport::writeDMLTextFrame(ww8::Frame const* pParentFrame, int nAnchorId,
1217  bool bTextBoxOnly)
1218 {
1219  bool bDMLAndVMLDrawingOpen = m_pImpl->getDMLAndVMLDrawingOpen();
1220  m_pImpl->setDMLAndVMLDrawingOpen(IsAnchorTypeInsideParagraph(pParentFrame));
1221 
1222  sax_fastparser::FSHelperPtr pFS = m_pImpl->getSerializer();
1223  const SwFrameFormat& rFrameFormat = pParentFrame->GetFrameFormat();
1224  const SwNodeIndex* pNodeIndex = rFrameFormat.GetContent().GetContentIdx();
1225 
1226  sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex() + 1 : 0;
1227  sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1228 
1229  //Save data here and restore when out of scope
1230  ExportDataSaveRestore aDataGuard(m_pImpl->getExport(), nStt, nEnd, pParentFrame);
1231 
1232  // When a frame has some low height, but automatically expanded due
1233  // to lots of contents, this size contains the real size.
1234  const Size aSize = pParentFrame->GetSize();
1235 
1236  uno::Reference<drawing::XShape> xShape;
1237  const SdrObject* pSdrObj = rFrameFormat.FindRealSdrObject();
1238  if (pSdrObj)
1239  xShape.set(const_cast<SdrObject*>(pSdrObj)->getUnoShape(), uno::UNO_QUERY);
1240  uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
1241  uno::Reference<beans::XPropertySetInfo> xPropSetInfo;
1242  if (xPropertySet.is())
1243  xPropSetInfo = xPropertySet->getPropertySetInfo();
1244 
1246  {
1247  drawing::TextVerticalAdjust eAdjust = drawing::TextVerticalAdjust_TOP;
1248  if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("TextVerticalAdjust"))
1249  xPropertySet->getPropertyValue("TextVerticalAdjust") >>= eAdjust;
1250  m_pImpl->getBodyPrAttrList()->add(XML_anchor,
1252  }
1253 
1254  if (!bTextBoxOnly)
1255  {
1256  startDMLAnchorInline(&rFrameFormat, aSize);
1257 
1258  sax_fastparser::FastAttributeList* pDocPrAttrList
1260  pDocPrAttrList->add(XML_id, OString::number(nAnchorId).getStr());
1261  pDocPrAttrList->add(
1262  XML_name, OUStringToOString(rFrameFormat.GetName(), RTL_TEXTENCODING_UTF8).getStr());
1263  sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList);
1264  pFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef);
1265 
1266  pFS->startElementNS(XML_a, XML_graphic, FSNS(XML_xmlns, XML_a),
1267  m_pImpl->getExport().GetFilter().getNamespaceURL(OOX_NS(dml)));
1268  pFS->startElementNS(XML_a, XML_graphicData, XML_uri,
1269  "http://schemas.microsoft.com/office/word/2010/wordprocessingShape");
1270  pFS->startElementNS(XML_wps, XML_wsp);
1271  pFS->singleElementNS(XML_wps, XML_cNvSpPr, XML_txBox, "1");
1272 
1273  uno::Any aRotation;
1274  m_pImpl->setDMLandVMLTextFrameRotation(0);
1275  if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag"))
1276  {
1277  uno::Sequence<beans::PropertyValue> propList;
1278  xPropertySet->getPropertyValue("FrameInteropGrabBag") >>= propList;
1279  auto pProp = std::find_if(propList.begin(), propList.end(),
1280  [](const beans::PropertyValue& rProp) {
1281  return rProp.Name == "mso-rotation-angle";
1282  });
1283  if (pProp != propList.end())
1284  aRotation = pProp->Value;
1285  }
1286  aRotation >>= m_pImpl->getDMLandVMLTextFrameRotation();
1287  OString sRotation(OString::number(
1288  oox::drawingml::ExportRotateClockwisify(m_pImpl->getDMLandVMLTextFrameRotation())));
1289  // Shape properties
1290  pFS->startElementNS(XML_wps, XML_spPr);
1291  if (m_pImpl->getDMLandVMLTextFrameRotation())
1292  {
1293  pFS->startElementNS(XML_a, XML_xfrm, XML_rot, sRotation);
1294  }
1295  else
1296  {
1297  pFS->startElementNS(XML_a, XML_xfrm);
1298  }
1299  pFS->singleElementNS(XML_a, XML_off, XML_x, "0", XML_y, "0");
1300  OString aWidth(OString::number(TwipsToEMU(aSize.Width())));
1301  OString aHeight(OString::number(TwipsToEMU(aSize.Height())));
1302  pFS->singleElementNS(XML_a, XML_ext, XML_cx, aWidth, XML_cy, aHeight);
1303  pFS->endElementNS(XML_a, XML_xfrm);
1304  OUString shapeType = "rect";
1305  if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag"))
1306  {
1307  uno::Sequence<beans::PropertyValue> propList;
1308  xPropertySet->getPropertyValue("FrameInteropGrabBag") >>= propList;
1309  auto pProp = std::find_if(propList.begin(), propList.end(),
1310  [](const beans::PropertyValue& rProp) {
1311  return rProp.Name == "mso-orig-shape-type";
1312  });
1313  if (pProp != propList.end())
1314  pProp->Value >>= shapeType;
1315  }
1316  //Empty shapeType will lead to corruption so to avoid that shapeType is set to default i.e. "rect"
1317  if (shapeType.isEmpty())
1318  shapeType = "rect";
1319 
1320  pFS->singleElementNS(XML_a, XML_prstGeom, XML_prst, shapeType);
1321  m_pImpl->setDMLTextFrameSyntax(true);
1322  m_pImpl->getExport().OutputFormat(pParentFrame->GetFrameFormat(), false, false, true);
1323  m_pImpl->setDMLTextFrameSyntax(false);
1324  writeDMLEffectLst(rFrameFormat);
1325  pFS->endElementNS(XML_wps, XML_spPr);
1326  }
1327 
1328  //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.
1329  if (!m_pImpl->getExport().m_bLinkedTextboxesHelperInitialized)
1330  {
1331  sal_Int32 nSeq = 0;
1332  for (auto& rEntry : m_pImpl->getExport().m_aLinkedTextboxesHelper)
1333  {
1334  //find the start of a textbox chain: has no PREVIOUS link, but does have NEXT link
1335  if (rEntry.second.sPrevChain.isEmpty() && !rEntry.second.sNextChain.isEmpty())
1336  {
1337  //assign this chain a unique ID and start a new sequence
1338  nSeq = 0;
1339  rEntry.second.nId = ++m_pImpl->getExport().m_nLinkedTextboxesChainId;
1340  rEntry.second.nSeq = nSeq;
1341 
1342  OUString sCheckForBrokenChains = rEntry.first;
1343 
1344  //follow the chain and assign the same id, and incremental sequence numbers.
1345  auto followChainIter
1346  = m_pImpl->getExport().m_aLinkedTextboxesHelper.find(rEntry.second.sNextChain);
1347  while (followChainIter != m_pImpl->getExport().m_aLinkedTextboxesHelper.end())
1348  {
1349  //verify that the NEXT textbox also points to me as the PREVIOUS.
1350  // A broken link indicates a leftover remnant that can be ignored.
1351  if (followChainIter->second.sPrevChain != sCheckForBrokenChains)
1352  break;
1353 
1354  followChainIter->second.nId = m_pImpl->getExport().m_nLinkedTextboxesChainId;
1355  followChainIter->second.nSeq = ++nSeq;
1356 
1357  //empty next chain indicates the end of the linked chain.
1358  if (followChainIter->second.sNextChain.isEmpty())
1359  break;
1360 
1361  sCheckForBrokenChains = followChainIter->first;
1362  followChainIter = m_pImpl->getExport().m_aLinkedTextboxesHelper.find(
1363  followChainIter->second.sNextChain);
1364  }
1365  }
1366  }
1367  m_pImpl->getExport().m_bLinkedTextboxesHelperInitialized = true;
1368  }
1369 
1370  m_pImpl->getExport().m_pParentFrame = nullptr;
1371  bool skipTxBxContent = false;
1372  bool isTxbxLinked = false;
1373 
1374  OUString sLinkChainName;
1375  if (xPropSetInfo.is())
1376  {
1377  if (xPropSetInfo->hasPropertyByName("LinkDisplayName"))
1378  xPropertySet->getPropertyValue("LinkDisplayName") >>= sLinkChainName;
1379  else if (xPropSetInfo->hasPropertyByName("ChainName"))
1380  xPropertySet->getPropertyValue("ChainName") >>= sLinkChainName;
1381  }
1382 
1383  // second, check if THIS textbox is linked and then decide whether to write the tag txbx or linkedTxbx
1384  auto linkedTextboxesIter = m_pImpl->getExport().m_aLinkedTextboxesHelper.find(sLinkChainName);
1385  if (linkedTextboxesIter != m_pImpl->getExport().m_aLinkedTextboxesHelper.end())
1386  {
1387  if ((linkedTextboxesIter->second.nId != 0) && (linkedTextboxesIter->second.nSeq != 0))
1388  {
1389  //not the first in the chain, so write the tag as linkedTxbx
1390  pFS->singleElementNS(XML_wps, XML_linkedTxbx, XML_id,
1391  OString::number(linkedTextboxesIter->second.nId), XML_seq,
1392  OString::number(linkedTextboxesIter->second.nSeq));
1393  /* no text content should be added to this tag,
1394  since the textbox is linked, the entire content
1395  is written in txbx block
1396  */
1397  skipTxBxContent = true;
1398  }
1399  else if ((linkedTextboxesIter->second.nId != 0) && (linkedTextboxesIter->second.nSeq == 0))
1400  {
1401  /* this is the first textbox in the chaining, we add the text content
1402  to this block*/
1403  //since the text box is linked, it needs an id.
1404  pFS->startElementNS(XML_wps, XML_txbx, XML_id,
1405  OString::number(linkedTextboxesIter->second.nId));
1406  isTxbxLinked = true;
1407  }
1408  }
1409 
1410  if (!skipTxBxContent)
1411  {
1412  if (!isTxbxLinked)
1413  pFS->startElementNS(XML_wps, XML_txbx); //text box is not linked, therefore no id.
1414 
1415  pFS->startElementNS(XML_w, XML_txbxContent);
1416 
1417  const SvxFrameDirectionItem& rDirection = rFrameFormat.GetFrameDir();
1418  if (rDirection.GetValue() == SvxFrameDirection::Vertical_RL_TB)
1419  m_pImpl->getBodyPrAttrList()->add(XML_vert, "eaVert");
1420  else if (rDirection.GetValue() == SvxFrameDirection::Vertical_LR_BT)
1421  m_pImpl->getBodyPrAttrList()->add(XML_vert, "vert270");
1422 
1423  {
1424  ::comphelper::FlagRestorationGuard const g(m_pImpl->m_bFlyFrameGraphic, true);
1425  comphelper::ValueRestorationGuard vg(m_pImpl->getExport().m_nTextTyp, TXT_TXTBOX);
1426  m_pImpl->getExport().WriteText();
1427  if (m_pImpl->getParagraphSdtOpen())
1428  {
1429  m_pImpl->getExport().DocxAttrOutput().EndParaSdtBlock();
1430  m_pImpl->setParagraphSdtOpen(false);
1431  }
1432  }
1433 
1434  pFS->endElementNS(XML_w, XML_txbxContent);
1435  pFS->endElementNS(XML_wps, XML_txbx);
1436  }
1437 
1438  // We need to init padding to 0, if it's not set.
1439  // In LO the default is 0 and so ins attributes are not set when padding is 0
1440  // but in MSO the default is 254 / 127, so we need to set 0 padding explicitly
1441  if (m_pImpl->getBodyPrAttrList())
1442  {
1443  if (!m_pImpl->getBodyPrAttrList()->hasAttribute(XML_lIns))
1444  m_pImpl->getBodyPrAttrList()->add(XML_lIns, OString::number(0));
1445  if (!m_pImpl->getBodyPrAttrList()->hasAttribute(XML_tIns))
1446  m_pImpl->getBodyPrAttrList()->add(XML_tIns, OString::number(0));
1447  if (!m_pImpl->getBodyPrAttrList()->hasAttribute(XML_rIns))
1448  m_pImpl->getBodyPrAttrList()->add(XML_rIns, OString::number(0));
1449  if (!m_pImpl->getBodyPrAttrList()->hasAttribute(XML_bIns))
1450  m_pImpl->getBodyPrAttrList()->add(XML_bIns, OString::number(0));
1451  }
1452 
1453  sax_fastparser::XFastAttributeListRef xBodyPrAttrList(m_pImpl->getBodyPrAttrList());
1454  m_pImpl->setBodyPrAttrList(nullptr);
1455  if (!bTextBoxOnly)
1456  {
1457  pFS->startElementNS(XML_wps, XML_bodyPr, xBodyPrAttrList);
1458  // AutoSize of the Text Frame.
1459  const SwFormatFrameSize& rSize = rFrameFormat.GetFrameSize();
1460  pFS->singleElementNS(
1461  XML_a,
1462  (rSize.GetHeightSizeType() == SwFrameSize::Variable ? XML_spAutoFit : XML_noAutofit));
1463  pFS->endElementNS(XML_wps, XML_bodyPr);
1464 
1465  pFS->endElementNS(XML_wps, XML_wsp);
1466  pFS->endElementNS(XML_a, XML_graphicData);
1467  pFS->endElementNS(XML_a, XML_graphic);
1468 
1469  // Relative size of the Text Frame.
1470  const sal_uInt8 nWidthPercent = rSize.GetWidthPercent();
1471  if (nWidthPercent && nWidthPercent != SwFormatFrameSize::SYNCED)
1472  {
1473  pFS->startElementNS(XML_wp14, XML_sizeRelH, XML_relativeFrom,
1474  (rSize.GetWidthPercentRelation() == text::RelOrientation::PAGE_FRAME
1475  ? "page"
1476  : "margin"));
1477  pFS->startElementNS(XML_wp14, XML_pctWidth);
1478  pFS->writeEscaped(OUString::number(nWidthPercent * oox::drawingml::PER_PERCENT));
1479  pFS->endElementNS(XML_wp14, XML_pctWidth);
1480  pFS->endElementNS(XML_wp14, XML_sizeRelH);
1481  }
1482  const sal_uInt8 nHeightPercent = rSize.GetHeightPercent();
1483  if (nHeightPercent && nHeightPercent != SwFormatFrameSize::SYNCED)
1484  {
1485  pFS->startElementNS(
1486  XML_wp14, XML_sizeRelV, XML_relativeFrom,
1487  (rSize.GetHeightPercentRelation() == text::RelOrientation::PAGE_FRAME ? "page"
1488  : "margin"));
1489  pFS->startElementNS(XML_wp14, XML_pctHeight);
1490  pFS->writeEscaped(OUString::number(nHeightPercent * oox::drawingml::PER_PERCENT));
1491  pFS->endElementNS(XML_wp14, XML_pctHeight);
1492  pFS->endElementNS(XML_wp14, XML_sizeRelV);
1493  }
1494 
1495  endDMLAnchorInline(&rFrameFormat);
1496  }
1497  m_pImpl->setDMLAndVMLDrawingOpen(bDMLAndVMLDrawingOpen);
1498 }
1499 
1500 void DocxSdrExport::writeVMLTextFrame(ww8::Frame const* pParentFrame, bool bTextBoxOnly)
1501 {
1502  bool bDMLAndVMLDrawingOpen = m_pImpl->getDMLAndVMLDrawingOpen();
1503  m_pImpl->setDMLAndVMLDrawingOpen(IsAnchorTypeInsideParagraph(pParentFrame));
1504 
1505  sax_fastparser::FSHelperPtr pFS = m_pImpl->getSerializer();
1506  const SwFrameFormat& rFrameFormat = pParentFrame->GetFrameFormat();
1507  const SwNodeIndex* pNodeIndex = rFrameFormat.GetContent().GetContentIdx();
1508 
1509  sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex() + 1 : 0;
1510  sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1511 
1512  //Save data here and restore when out of scope
1513  ExportDataSaveRestore aDataGuard(m_pImpl->getExport(), nStt, nEnd, pParentFrame);
1514 
1515  // When a frame has some low height, but automatically expanded due
1516  // to lots of contents, this size contains the real size.
1517  const Size aSize = pParentFrame->GetSize();
1518  m_pImpl->setFlyFrameSize(&aSize);
1519 
1520  m_pImpl->setTextFrameSyntax(true);
1523  m_pImpl->getTextFrameStyle() = "position:absolute";
1524  if (!bTextBoxOnly)
1525  {
1526  OString sRotation(OString::number(m_pImpl->getDMLandVMLTextFrameRotation() / -100));
1527  m_pImpl->getExport()
1528  .SdrExporter()
1529  .getTextFrameStyle()
1530  .append(";rotation:")
1531  .append(sRotation);
1532  }
1533  m_pImpl->getExport().OutputFormat(pParentFrame->GetFrameFormat(), false, false, true);
1534  m_pImpl->getFlyAttrList()->add(XML_style, m_pImpl->getTextFrameStyle().makeStringAndClear());
1535 
1536  const SdrObject* pObject = pParentFrame->GetFrameFormat().FindRealSdrObject();
1537  if (pObject != nullptr)
1538  {
1539  OUString sAnchorId = lclGetAnchorIdFromGrabBag(pObject);
1540  if (!sAnchorId.isEmpty())
1541  m_pImpl->getFlyAttrList()->addNS(XML_w14, XML_anchorId,
1542  OUStringToOString(sAnchorId, RTL_TEXTENCODING_UTF8));
1543  }
1544  sax_fastparser::XFastAttributeListRef xFlyAttrList(m_pImpl->getFlyAttrList().get());
1545  m_pImpl->getFlyAttrList().clear();
1546  sax_fastparser::XFastAttributeListRef xTextboxAttrList(m_pImpl->getTextboxAttrList().get());
1547  m_pImpl->getTextboxAttrList().clear();
1548  m_pImpl->setTextFrameSyntax(false);
1549  m_pImpl->setFlyFrameSize(nullptr);
1550  m_pImpl->getExport().m_pParentFrame = nullptr;
1551 
1552  if (!bTextBoxOnly)
1553  {
1554  pFS->startElementNS(XML_w, XML_pict);
1555  pFS->startElementNS(XML_v, XML_rect, xFlyAttrList);
1556  m_pImpl->textFrameShadow(rFrameFormat);
1557  if (m_pImpl->getFlyFillAttrList().is())
1558  {
1559  sax_fastparser::XFastAttributeListRef xFlyFillAttrList(
1560  m_pImpl->getFlyFillAttrList().get());
1561  m_pImpl->getFlyFillAttrList().clear();
1562  pFS->singleElementNS(XML_v, XML_fill, xFlyFillAttrList);
1563  }
1564  if (m_pImpl->getDashLineStyleAttr().is())
1565  {
1566  sax_fastparser::XFastAttributeListRef xDashLineStyleAttr(
1567  m_pImpl->getDashLineStyleAttr().get());
1568  m_pImpl->getDashLineStyleAttr().clear();
1569  pFS->singleElementNS(XML_v, XML_stroke, xDashLineStyleAttr);
1570  }
1571  pFS->startElementNS(XML_v, XML_textbox, xTextboxAttrList);
1572  }
1573  pFS->startElementNS(XML_w, XML_txbxContent);
1574  {
1575  ::comphelper::FlagRestorationGuard const g(m_pImpl->m_bFlyFrameGraphic, true);
1576  comphelper::ValueRestorationGuard vg(m_pImpl->getExport().m_nTextTyp, TXT_TXTBOX);
1577  m_pImpl->getExport().WriteText();
1578  if (m_pImpl->getParagraphSdtOpen())
1579  {
1580  m_pImpl->getExport().DocxAttrOutput().EndParaSdtBlock();
1581  m_pImpl->setParagraphSdtOpen(false);
1582  }
1583  }
1584  pFS->endElementNS(XML_w, XML_txbxContent);
1585  if (!bTextBoxOnly)
1586  {
1587  pFS->endElementNS(XML_v, XML_textbox);
1588 
1589  if (m_pImpl->getFlyWrapAttrList())
1590  {
1591  sax_fastparser::XFastAttributeListRef xFlyWrapAttrList(m_pImpl->getFlyWrapAttrList());
1592  m_pImpl->setFlyWrapAttrList(nullptr);
1593  pFS->singleElementNS(XML_w10, XML_wrap, xFlyWrapAttrList);
1594  }
1595 
1596  pFS->endElementNS(XML_v, XML_rect);
1597  pFS->endElementNS(XML_w, XML_pict);
1598  }
1599 
1600  m_pImpl->setDMLAndVMLDrawingOpen(bDMLAndVMLDrawingOpen);
1601 }
1602 
1603 bool DocxSdrExport::isTextBox(const SwFrameFormat& rFrameFormat)
1604 {
1605  return SwTextBoxHelper::isTextBox(&rFrameFormat, RES_FLYFRMFMT);
1606 }
1607 
1608 /* 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_uInt16 GetLower() const
sal_Int32 & getDMLandVMLTextFrameRotation()
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)
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_uInt8 GetTransparency() const
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)
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:66
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:332
rtl::Reference< sax_fastparser::FastAttributeList > & getFlyFillAttrList()
void writeDiagram(const SdrObject *sdrObject, const SwFrameFormat &rFrameFormat, int nDiagramId)
Writes a diagram (smartart).
void setDMLAndVMLDrawingOpen(bool bDMLAndVMLDrawingOpen)
sal_Int32 m_nDMLandVMLTextFrameRotation
List of TextBoxes in this document: they are exported as part of their shape, never alone...
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:111
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?
const Size * getFlyFrameSize() const
const SwFormatSurround & GetSurround(bool=true) const
Definition: fmtsrnd.hxx:66
bool HasTextBoxContent(sal_uInt32 nShapeType)
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.
OBJ_LINE
Style of a layout element.
Definition: frmfmt.hxx:57
#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:878
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:512
#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
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:119
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
virtual SdrLayerID GetLayer() const
sal_Int16 GetHeightPercentRelation() const
Definition: fmtfsize.hxx:89
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
void setParagraphSdtOpen(bool bParagraphSdtOpen)
Set if paragraph sdt open in the current drawing.
OString OUStringToOString(const OUString &str, ConnectionSettings const *settings)
rtl::Reference< sax_fastparser::FastAttributeList > m_pDashLineStyleAttr
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:685
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
T ExportRotateClockwisify(T input)
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.
static OString lcl_ConvertTransparency(const Color &rColor)
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:116
Frame is variable in Var-direction.
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
void setDrawingOpen(bool bDrawingOpen)
void setParagraphHasDrawing(bool bParagraphHasDrawing)
void setDMLandVMLTextFrameRotation(sal_Int32 nDMLandVMLTextFrameRotation)
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:2739
void add(sal_Int32 nToken, const char *pValue)
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
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:74
EnumT GetValue() const
const SvxShadowItem & GetShadow(bool=true) const
Definition: frmatr.hxx:88