LibreOffice Module sw (master)  1
rtfsdrexport.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  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include "rtfsdrexport.hxx"
21 #include <memory>
22 #include "rtfattributeoutput.hxx"
23 #include <svtools/rtfkeywd.hxx>
24 #include <svtools/unitconv.hxx>
26 #include <editeng/editobj.hxx>
27 #include <editeng/editids.hrc>
28 #include <editeng/fontitem.hxx>
29 #include <editeng/fhgtitem.hxx>
30 #include <svx/svdotext.hxx>
31 #include <svx/unoapi.hxx>
32 #include <vcl/cvtgrf.hxx>
33 #include <textboxhelper.hxx>
34 #include <dcontact.hxx>
35 #include <tools/diagnose_ex.h>
36 #include <sal/log.hxx>
37 #include <algorithm>
38 #include "rtfexport.hxx"
39 
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/graphic/XGraphic.hpp>
42 
43 using namespace css;
44 
46  : EscherEx(std::make_shared<EscherExGlobal>(), nullptr)
47  , m_rExport(rExport)
48  , m_rAttrOutput(static_cast<RtfAttributeOutput&>(m_rExport.AttrOutput()))
49  , m_pSdrObject(nullptr)
50  , m_nShapeType(ESCHER_ShpInst_Nil)
51  , m_nShapeFlags(ShapeFlag::NONE)
52  , m_aShapeStyle(200)
53  , m_pShapeTypeWritten(new bool[ESCHER_ShpInst_COUNT])
54 {
55  mnGroupLevel = 1;
56  memset(m_pShapeTypeWritten.get(), 0, ESCHER_ShpInst_COUNT * sizeof(bool));
57 }
58 
60 {
61  delete mpOutStrm;
62  mpOutStrm = nullptr;
63 }
64 
65 void RtfSdrExport::OpenContainer(sal_uInt16 nEscherContainer, int nRecInstance)
66 {
67  EscherEx::OpenContainer(nEscherContainer, nRecInstance);
68 
69  if (nEscherContainer == ESCHER_SpContainer)
70  {
72  m_aShapeStyle.setLength(0);
73  m_aShapeStyle.ensureCapacity(200);
74  m_aShapeProps.clear();
75  }
76 }
77 
79 {
80  if (mRecTypes.back() == ESCHER_SpContainer)
81  {
82  // write the shape now when we have all the info
83  sal_Int32 nShapeElement = StartShape();
84  EndShape(nShapeElement);
85 
86  // cleanup
88  }
89 
91 }
92 
93 sal_uInt32 RtfSdrExport::EnterGroup(const OUString& /*rShapeName*/,
94  const tools::Rectangle* /*pRect*/)
95 {
96  m_bInGroup = true;
97  return GenerateShapeId();
98 }
99 
101 
102 void RtfSdrExport::AddShape(sal_uInt32 nShapeType, ShapeFlag nShapeFlags, sal_uInt32 /*nShapeId*/)
103 {
104  m_nShapeType = nShapeType;
105  m_nShapeFlags = nShapeFlags;
106 }
107 
108 static sal_uInt16 impl_GetUInt16(const sal_uInt8*& pVal)
109 {
110  sal_uInt16 nRet = *pVal++;
111  nRet += (*pVal++) << 8;
112  return nRet;
113 }
114 
115 static sal_Int32 impl_GetPointComponent(const sal_uInt8*& pVal, std::size_t& rVerticesPos,
116  sal_uInt16 nPointSize)
117 {
118  sal_Int32 nRet = 0;
119  if ((nPointSize == 0xfff0) || (nPointSize == 4))
120  {
121  sal_uInt16 nUnsigned = *pVal++;
122  nUnsigned += (*pVal++) << 8;
123  rVerticesPos += 2;
124 
125  nRet = sal_Int16(nUnsigned);
126  }
127  else if (nPointSize == 8)
128  {
129  sal_uInt32 nUnsigned = *pVal++;
130  nUnsigned += (*pVal++) << 8;
131  nUnsigned += (*pVal++) << 16;
132  nUnsigned += (*pVal++) << 24;
133  rVerticesPos += 4;
134 
135  nRet = nUnsigned;
136  }
137 
138  return nRet;
139 }
140 
142 {
144  return;
145 
147  AddLineDimensions(rRect);
148  else
150 
151  // properties
152  const EscherProperties& rOpts = rProps.GetOpts();
153  for (const auto& rOpt : rOpts)
154  {
155  sal_uInt16 nId = (rOpt.nPropId & 0x0FFF);
156 
157  switch (nId)
158  {
160  {
161  int nWrapType = 0;
162  switch (rOpt.nPropValue)
163  {
164  case ESCHER_WrapSquare:
165  nWrapType = 2;
166  break;
167  case ESCHER_WrapByPoints:
168  nWrapType = 4;
169  break;
170  case ESCHER_WrapNone:
171  nWrapType = 3;
172  break;
174  nWrapType = 1;
175  break;
176  case ESCHER_WrapThrough:
177  nWrapType = 5;
178  break;
179  }
180  if (nWrapType)
182  .append(static_cast<sal_Int32>(nWrapType));
183  }
184  break;
186  m_aShapeProps.insert(
187  std::pair<OString, OString>("fillColor", OString::number(rOpt.nPropValue)));
188  break;
190  m_aShapeProps.insert(
191  std::pair<OString, OString>("fillBackColor", OString::number(rOpt.nPropValue)));
192  break;
194  m_aShapeProps.insert(
195  std::pair<OString, OString>("anchorText", OString::number(rOpt.nPropValue)));
196  break;
198  if (rOpt.nPropValue)
199  m_aShapeProps.insert(
200  std::pair<OString, OString>("fNoFillHitTest", OString::number(1)));
201  break;
203  // for some reason the value is set to 0x90000 if lines are switched off
204  if (rOpt.nPropValue == 0x90000)
205  m_aShapeProps.insert(std::pair<OString, OString>("fLine", OString::number(0)));
206  break;
208  m_aShapeProps.insert(
209  std::pair<OString, OString>("lineColor", OString::number(rOpt.nPropValue)));
210  break;
212  m_aShapeProps.insert(
213  std::pair<OString, OString>("lineBackColor", OString::number(rOpt.nPropValue)));
214  break;
216  m_aShapeProps.insert(
217  std::pair<OString, OString>("lineJoinStyle", OString::number(rOpt.nPropValue)));
218  break;
220  if (rOpt.nPropValue)
221  m_aShapeProps.insert(std::pair<OString, OString>("fshadowObscured", "1"));
222  break;
223  case ESCHER_Prop_geoLeft:
224  case ESCHER_Prop_geoTop:
225  {
226  sal_uInt32 nLeft = 0;
227  sal_uInt32 nTop = 0;
228 
229  if (nId == ESCHER_Prop_geoLeft)
230  {
231  nLeft = rOpt.nPropValue;
232  rProps.GetOpt(ESCHER_Prop_geoTop, nTop);
233  }
234  else
235  {
236  nTop = rOpt.nPropValue;
237  rProps.GetOpt(ESCHER_Prop_geoLeft, nLeft);
238  }
239 
240  m_aShapeProps.insert(
241  std::pair<OString, OString>("geoLeft", OString::number(sal_Int32(nLeft))));
242  m_aShapeProps.insert(
243  std::pair<OString, OString>("geoTop", OString::number(sal_Int32(nTop))));
244  }
245  break;
246 
249  {
250  sal_uInt32 nLeft = 0;
251  sal_uInt32 nRight = 0;
252  sal_uInt32 nTop = 0;
253  sal_uInt32 nBottom = 0;
254  rProps.GetOpt(ESCHER_Prop_geoLeft, nLeft);
255  rProps.GetOpt(ESCHER_Prop_geoTop, nTop);
256 
257  if (nId == ESCHER_Prop_geoRight)
258  {
259  nRight = rOpt.nPropValue;
260  rProps.GetOpt(ESCHER_Prop_geoBottom, nBottom);
261  }
262  else
263  {
264  nBottom = rOpt.nPropValue;
265  rProps.GetOpt(ESCHER_Prop_geoRight, nRight);
266  }
267 
268  m_aShapeProps.insert(std::pair<OString, OString>(
269  "geoRight", OString::number(sal_Int32(nRight) - sal_Int32(nLeft))));
270  m_aShapeProps.insert(std::pair<OString, OString>(
271  "geoBottom", OString::number(sal_Int32(nBottom) - sal_Int32(nTop))));
272  }
273  break;
276  {
277  EscherPropSortStruct aVertices;
279 
280  if (rProps.GetOpt(ESCHER_Prop_pVertices, aVertices)
281  && rProps.GetOpt(ESCHER_Prop_pSegmentInfo, aSegments)
282  && aVertices.nProp.size() >= 6 && aSegments.nProp.size() >= 6)
283  {
284  const sal_uInt8* pVerticesIt = aVertices.nProp.data() + 6;
285  std::size_t nVerticesPos = 6;
286  const sal_uInt8* pSegmentIt = aSegments.nProp.data();
287 
288  OStringBuffer aSegmentInfo(512);
289  OStringBuffer aVerticies(512);
290 
291  sal_uInt16 nPointSize = aVertices.nProp[4] + (aVertices.nProp[5] << 8);
292 
293  // number of segments
294  sal_uInt16 nSegments = impl_GetUInt16(pSegmentIt);
295  sal_Int32 nVertices = 0;
296  aSegmentInfo.append("2;").append(static_cast<sal_Int32>(nSegments));
297  pSegmentIt += 4;
298 
299  for (; nSegments; --nSegments)
300  {
301  sal_uInt16 nSeg = impl_GetUInt16(pSegmentIt);
302 
303  // The segment type is stored in the upper 3 bits
304  // and segment count is stored in the lower 13
305  // bits.
306  unsigned char nSegmentType = (nSeg & 0xE000) >> 13;
307  unsigned short nSegmentCount = nSeg & 0x03FF;
308 
309  aSegmentInfo.append(';').append(static_cast<sal_Int32>(nSeg));
310  switch (nSegmentType)
311  {
312  case msopathLineTo:
313  for (unsigned short i = 0; i < nSegmentCount; ++i)
314  {
315  sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nVerticesPos,
316  nPointSize);
317  sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nVerticesPos,
318  nPointSize);
319  aVerticies.append(";(")
320  .append(nX)
321  .append(",")
322  .append(nY)
323  .append(")");
324  nVertices++;
325  }
326  break;
327  case msopathMoveTo:
328  {
329  sal_Int32 nX
330  = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
331  sal_Int32 nY
332  = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
333  aVerticies.append(";(").append(nX).append(",").append(nY).append(
334  ")");
335  nVertices++;
336  break;
337  }
338  case msopathCurveTo:
339  for (unsigned short j = 0; j < nSegmentCount; ++j)
340  {
341  for (int i = 0; i < 3; i++)
342  {
343  sal_Int32 nX = impl_GetPointComponent(
344  pVerticesIt, nVerticesPos, nPointSize);
345  sal_Int32 nY = impl_GetPointComponent(
346  pVerticesIt, nVerticesPos, nPointSize);
347  aVerticies.append(";(")
348  .append(nX)
349  .append(",")
350  .append(nY)
351  .append(")");
352  nVertices++;
353  }
354  }
355  break;
356  case msopathEscape:
357  {
358  // If the segment type is msopathEscape, the lower 13 bits are
359  // divided in a 5 bit escape code and 8 bit
360  // vertex count (not segment count!)
361  unsigned char nVertexCount = nSegmentCount & 0x00FF;
362  nVerticesPos += nVertexCount;
363  break;
364  }
365  case msopathClientEscape:
366  case msopathClose:
367  case msopathEnd:
368  break;
369  default:
370  SAL_WARN("sw.rtf", "Totally b0rked");
371  break;
372  }
373  }
374 
375  if (!aVerticies.isEmpty())
376  {
377  // We know the number of vertices at the end only, so we have to prepend them here.
378  m_aShapeProps.insert(std::pair<OString, OString>(
379  "pVerticies",
380  "8;" + OString::number(nVertices) + aVerticies.makeStringAndClear()));
381  }
382  if (!aSegmentInfo.isEmpty())
383  m_aShapeProps.insert(std::pair<OString, OString>(
384  "pSegmentInfo", aSegmentInfo.makeStringAndClear()));
385  }
386  else
387  SAL_INFO(
388  "sw.rtf",
389  OSL_THIS_FUNC
390  << ": unhandled shape path, missing either pVertices or pSegmentInfo");
391  }
392  break;
394  // noop, we use pSegmentInfo instead
395  break;
396  case ESCHER_Prop_fFillOK:
397  if (!rOpt.nPropValue)
398  m_aShapeProps.insert(std::pair<OString, OString>("fFillOK", "0"));
399  break;
401  m_aShapeProps.insert(
402  std::pair<OString, OString>("dxTextLeft", OString::number(rOpt.nPropValue)));
403  break;
405  m_aShapeProps.insert(
406  std::pair<OString, OString>("dyTextTop", OString::number(rOpt.nPropValue)));
407  break;
409  m_aShapeProps.insert(
410  std::pair<OString, OString>("dxTextRight", OString::number(rOpt.nPropValue)));
411  break;
413  m_aShapeProps.insert(
414  std::pair<OString, OString>("dyTextBottom", OString::number(rOpt.nPropValue)));
415  break;
417  // Size text to fit shape size: not supported by RTF
418  break;
420  m_aShapeProps.insert(
421  std::pair<OString, OString>("adjustValue", OString::number(rOpt.nPropValue)));
422  break;
424  m_aShapeProps.insert(
425  std::pair<OString, OString>("txflTextFlow", OString::number(rOpt.nPropValue)));
426  break;
428  m_aShapeProps.insert(
429  std::pair<OString, OString>("fillType", OString::number(rOpt.nPropValue)));
430  break;
432  m_aShapeProps.insert(
433  std::pair<OString, OString>("fillOpacity", OString::number(rOpt.nPropValue)));
434  break;
436  {
437  OStringBuffer aBuf;
438  aBuf.append('{')
441  .append(SAL_NEWLINE_STRING);
442  int nHeaderSize
443  = 25; // The first bytes are WW8-specific, we're only interested in the PNG
444  aBuf.append(msfilter::rtfutil::WriteHex(rOpt.nProp.data() + nHeaderSize,
445  rOpt.nProp.size() - nHeaderSize));
446  aBuf.append('}');
447  m_aShapeProps.insert(
448  std::pair<OString, OString>("fillBlip", aBuf.makeStringAndClear()));
449  }
450  break;
451  default:
452  SAL_INFO("sw.rtf", OSL_THIS_FUNC << ": unhandled property: " << nId
453  << " (value: " << rOpt.nPropValue << ")");
454  break;
455  }
456  }
457 }
458 
460 {
461  // We get the position relative to (the current?) character
462  m_aShapeProps.insert(std::pair<OString, OString>("posrelh", "3"));
463 
464  if (m_nShapeFlags & ShapeFlag::FlipV)
465  m_aShapeProps.insert(std::pair<OString, OString>("fFlipV", "1"));
466 
467  if (m_nShapeFlags & ShapeFlag::FlipH)
468  m_aShapeProps.insert(std::pair<OString, OString>("fFlipH", "1"));
469 
470  // the actual dimensions
471  m_aShapeStyle.append(OOO_STRING_SVTOOLS_RTF_SHPLEFT).append(rRectangle.Left());
472  m_aShapeStyle.append(OOO_STRING_SVTOOLS_RTF_SHPTOP).append(rRectangle.Top());
473  m_aShapeStyle.append(OOO_STRING_SVTOOLS_RTF_SHPRIGHT).append(rRectangle.Right());
474  m_aShapeStyle.append(OOO_STRING_SVTOOLS_RTF_SHPBOTTOM).append(rRectangle.Bottom());
475 }
476 
477 void RtfSdrExport::AddRectangleDimensions(OStringBuffer& rBuffer,
478  const tools::Rectangle& rRectangle)
479 {
480  // We get the position relative to (the current?) character
481  m_aShapeProps.insert(std::pair<OString, OString>("posrelh", "3"));
482 
483  rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPLEFT).append(rRectangle.Left());
484  rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPTOP).append(rRectangle.Top());
485  rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPRIGHT).append(rRectangle.Right());
486  rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPBOTTOM).append(rRectangle.Bottom());
487 }
488 
489 extern const char* pShapeTypes[];
490 
491 static void lcl_AppendSP(OStringBuffer& rRunText, const char cName[], const OString& rValue)
492 {
493  rRunText.append('{')
495  .append('{')
496  .append(OOO_STRING_SVTOOLS_RTF_SN " ")
497  .append(cName)
498  .append('}')
499  .append('{')
500  .append(OOO_STRING_SVTOOLS_RTF_SV " ")
501  .append(rValue)
502  .append('}')
503  .append('}');
504 }
505 
507 {
508  // Get the Graphic object from the Sdr one.
509  uno::Reference<drawing::XShape> xShape
510  = GetXShapeForSdrObject(const_cast<SdrObject*>(m_pSdrObject));
511  uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
512 
513  uno::Reference<graphic::XGraphic> xGraphic;
514 
515  Graphic aGraphic;
516 
517  try
518  {
519  xPropertySet->getPropertyValue("Graphic") >>= xGraphic;
520  }
521  catch (beans::UnknownPropertyException const&)
522  {
523  DBG_UNHANDLED_EXCEPTION("sw.rtf");
524  }
525 
526  if (xGraphic.is())
527  {
528  aGraphic = Graphic(xGraphic);
529  }
530 
531  // Export it to a stream.
532  SvMemoryStream aStream;
533  (void)GraphicConverter::Export(aStream, aGraphic, ConvertDataFormat::PNG);
534  sal_uInt32 nSize = aStream.TellEnd();
535  auto pGraphicAry = static_cast<sal_uInt8 const*>(aStream.GetData());
536 
537  Size aMapped(aGraphic.GetPrefSize());
538 
539  // Add it to the properties.
541  aBuf->append('{').append(OOO_STRING_SVTOOLS_RTF_PICT).append(OOO_STRING_SVTOOLS_RTF_PNGBLIP);
542  aBuf->append(OOO_STRING_SVTOOLS_RTF_PICW).append(sal_Int32(aMapped.Width()));
543  aBuf->append(OOO_STRING_SVTOOLS_RTF_PICH)
544  .append(sal_Int32(aMapped.Height()))
545  .append(SAL_NEWLINE_STRING);
546  aBuf->append(msfilter::rtfutil::WriteHex(pGraphicAry, nSize));
547  aBuf->append('}');
548  m_aShapeProps.insert(std::pair<OString, OString>("pib", aBuf.makeStringAndClear()));
549 }
550 
552 {
554  return -1;
555 
556  m_aShapeProps.insert(std::pair<OString, OString>("shapeType", OString::number(m_nShapeType)));
559 
560  m_rAttrOutput.RunText().append('{').append(OOO_STRING_SVTOOLS_RTF_SHP);
562  .append('{')
565 
566  m_rAttrOutput.RunText().append(m_aShapeStyle.makeStringAndClear());
567  // Ignore \shpbxpage, \shpbxmargin, and \shpbxcolumn, in favor of the posrelh property.
569  // Ignore \shpbypage, \shpbymargin, and \shpbycolumn, in favor of the posrelh property.
571 
572  // Write ZOrder.
573  if (!m_bInGroup)
574  {
575  // Order inside the group shape is not relevant for the flat shape list
576  // we write.
578  m_rAttrOutput.RunText().append(OString::number(m_pSdrObject->GetOrdNum()));
579  }
580 
581  for (auto it = m_aShapeProps.rbegin(); it != m_aShapeProps.rend(); ++it)
582  lcl_AppendSP(m_rAttrOutput.RunText(), (*it).first.getStr(), (*it).second);
583 
584  lcl_AppendSP(m_rAttrOutput.RunText(), "wzDescription",
587  lcl_AppendSP(
588  m_rAttrOutput.RunText(), "wzName",
590 
591  // now check if we have some text
592  const SwFrameFormat* pShape = FindFrameFormat(m_pSdrObject);
593  if (pShape)
594  {
595  if (SwFrameFormat* pTextBox
597  {
598  ww8::Frame* pFrame = nullptr;
599  for (auto& rFrame : m_rExport.m_aFrames)
600  {
601  if (pTextBox == &rFrame.GetFrameFormat())
602  {
603  pFrame = &rFrame;
604  break;
605  }
606  }
607 
608  if (pFrame)
609  m_rAttrOutput.writeTextFrame(*pFrame, /*bTextBox=*/true);
610  return m_nShapeType;
611  }
612  }
613 
614  auto pTextObj = dynamic_cast<const SdrTextObj*>(m_pSdrObject);
615  if (pTextObj)
616  {
617  const OutlinerParaObject* pParaObj = nullptr;
618  std::unique_ptr<const OutlinerParaObject> pOwnedParaObj;
619 
620  /*
621  #i13885#
622  When the object is actively being edited, that text is not set into
623  the objects normal text object, but lives in a separate object.
624  */
625  if (pTextObj->IsTextEditActive())
626  {
627  pOwnedParaObj = pTextObj->GetEditOutlinerParaObject();
628  pParaObj = pOwnedParaObj.get();
629  }
630  else
631  {
632  pParaObj = pTextObj->GetOutlinerParaObject();
633  }
634 
635  if (pParaObj)
636  {
637  // this is reached only in case some text is attached to the shape
638  // Watermark or TextBox?
639  if (pTextObj->TakeObjNameSingul().match("Text Frame"))
640  WriteOutliner(*pParaObj, TXT_HFTXTBOX);
641  else
642  {
643  const EditTextObject& rEditObj = pParaObj->GetTextObject();
644  const SfxItemSet& rItemSet = rEditObj.GetParaAttribs(0);
645 
646  lcl_AppendSP(m_rAttrOutput.RunText(), "gtextUNICODE",
649 
650  auto pFontFamily
651  = static_cast<const SvxFontItem*>(rItemSet.GetItem(SID_ATTR_CHAR_FONT));
652  if (pFontFamily)
653  {
654  lcl_AppendSP(m_rAttrOutput.RunText(), "gtextFont",
655  msfilter::rtfutil::OutString(pFontFamily->GetFamilyName(),
657  }
658 
659  auto pFontHeight = static_cast<const SvxFontHeightItem*>(
660  rItemSet.GetItem(SID_ATTR_CHAR_FONTHEIGHT));
661  if (pFontHeight)
662  {
663  long nFontHeight = TransformMetric(pFontHeight->GetHeight(), FieldUnit::TWIP,
664  FieldUnit::POINT);
665  lcl_AppendSP(
666  m_rAttrOutput.RunText(), "gtextSize",
667  msfilter::rtfutil::OutString(OUString::number(nFontHeight * RTF_MULTIPLIER),
669  }
670 
671  // RTF angle: 0-360 * 2^16 clockwise
672  // LO angle: 0-360 * 100 counter-clockwise
673  sal_Int32 nRotation
674  = -1 * pTextObj->GetGeoStat().nRotationAngle * RTF_MULTIPLIER / 100;
675  lcl_AppendSP(m_rAttrOutput.RunText(), "rotation",
676  msfilter::rtfutil::OutString(OUString::number(nRotation),
678  }
679  }
680  }
681 
682  return m_nShapeType;
683 }
684 
686 {
687  SAL_INFO("sw.rtf", OSL_THIS_FUNC << " start");
688 
689  const EditTextObject& rEditObj = rParaObj.GetTextObject();
690  MSWord_SdrAttrIter aAttrIter(m_rExport, rEditObj, eType);
691 
692  sal_Int32 nPara = rEditObj.GetParagraphCount();
693 
694  bool bShape = eType == TXT_HFTXTBOX;
695  if (bShape)
696  m_rAttrOutput.RunText().append('{').append(OOO_STRING_SVTOOLS_RTF_SHPTXT).append(' ');
697  for (sal_Int32 n = 0; n < nPara; ++n)
698  {
699  if (n)
700  aAttrIter.NextPara(n);
701 
702  rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet();
703 
704  OUString aStr(rEditObj.GetText(n));
705  sal_Int32 nCurrentPos = 0;
706  const sal_Int32 nEnd = aStr.getLength();
707 
708  aAttrIter.OutParaAttr(false);
709  m_rAttrOutput.RunText().append(m_rAttrOutput.Styles().makeStringAndClear());
710  m_rAttrOutput.RunText().append(m_rAttrOutput.StylesEnd().makeStringAndClear());
711 
712  do
713  {
714  const sal_Int32 nNextAttr = std::min(aAttrIter.WhereNext(), nEnd);
715  rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet();
716 
717  aAttrIter.OutAttr(nCurrentPos);
718  m_rAttrOutput.RunText().append('{');
719  m_rAttrOutput.RunText().append(m_rAttrOutput.Styles().makeStringAndClear());
720  m_rAttrOutput.RunText().append(m_rAttrOutput.StylesEnd().makeStringAndClear());
722  bool bTextAtr = aAttrIter.IsTextAttr(nCurrentPos);
723  if (!bTextAtr)
724  {
725  OUString aOut(aStr.copy(nCurrentPos, nNextAttr - nCurrentPos));
726  m_rAttrOutput.RunText().append(msfilter::rtfutil::OutString(aOut, eChrSet));
727  }
728 
729  m_rAttrOutput.RunText().append('}');
730 
731  nCurrentPos = nNextAttr;
732  eChrSet = eNextChrSet;
733  aAttrIter.NextPos();
734  } while (nCurrentPos < nEnd);
735  if (bShape || n + 1 < nPara)
737  }
738  if (bShape)
739  m_rAttrOutput.RunText().append('}');
740 
741  SAL_INFO("sw.rtf", OSL_THIS_FUNC << " end");
742 }
743 
744 void RtfSdrExport::EndShape(sal_Int32 nShapeElement)
745 {
746  if (nShapeElement >= 0)
747  {
748  // end of the shape
749  m_rAttrOutput.RunText().append('}').append('}');
750  }
751 }
752 
754 {
755  m_pSdrObject = &rObj;
757 }
758 
759 bool RtfSdrExport::isTextBox(const SwFrameFormat& rFrameFormat)
760 {
761  return SwTextBoxHelper::isTextBox(&rFrameFormat, RES_FLYFRMFMT);
762 }
763 
764 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unique_ptr< bool[]> m_pShapeTypeWritten
Remember which shape types we had already written.
#define ESCHER_ShpInst_Nil
Wrapper around OStringBuffers, so less hexdump of graphics have to be kept in memory during RTF expor...
ESCHER_WrapSquare
void OutAttr(sal_Int32 nSwPos)
Definition: wrtw8esh.cxx:1127
sal_Int32 WhereNext() const
Definition: wrtww8.hxx:1460
long TransformMetric(long nVal, FieldUnit aOld, FieldUnit aNew)
#define OOO_STRING_SVTOOLS_RTF_SHPRIGHT
OStringBuffer & StylesEnd()
EscherProperties GetOpts() const
#define ESCHER_Prop_geoRight
#define ESCHER_Prop_geoLeft
msopathCurveTo
ESCHER_WrapTopBottom
#define ESCHER_Prop_fshadowObscured
#define OOO_STRING_SVTOOLS_RTF_SN
#define OOO_STRING_SVTOOLS_RTF_PNGBLIP
rtl_TextEncoding GetNodeCharSet() const
Definition: wrtww8.hxx:1462
void OpenContainer(sal_uInt16 nEscherContainer, int nRecInstance=0) override
#define ESCHER_Prop_dyTextTop
msopathEnd
SvStream * mpOutStrm
msopathLineTo
rtl_TextEncoding GetCurrentEncoding() const
Definition: rtfexport.hxx:176
ESCHER_WrapThrough
void OutParaAttr(bool bCharAttr, const std::set< sal_uInt16 > *pWhichsToIgnore=nullptr)
Definition: wrtw8esh.cxx:1284
void impl_writeGraphic()
Exports the pib property of the shape.
#define ESCHER_Prop_geoBottom
std::vector< sal_uInt8 > nProp
OUString GetDescription() const
std::vector< sal_uInt16 > mRecTypes
#define ESCHER_Prop_pVertices
sal_uInt32 AddSdrObject(const SdrObject &rObj, bool ooxmlExport=false)
aBuf
sal_Int16 nId
#define OOO_STRING_SVTOOLS_RTF_PICT
#define ESCHER_Prop_txflTextFlow
ESCHER_WrapNone
Used to export formatted text associated to drawings.
Definition: wrtww8.hxx:1424
#define OOO_STRING_SVTOOLS_RTF_PICH
static SwFrameFormat * getOtherTextBoxFormat(const SwFrameFormat *pFormat, sal_uInt16 nType)
If we have an associated TextFrame, then return that.
#define ESCHER_Prop_pSegmentInfo
static bool isTextBox(const SwFrameFormat &rFrameFormat)
Is this a standalone TextFrame, or used as a TextBox of a shape?
virtual sal_uInt32 GenerateShapeId()
virtual sal_uInt64 TellEnd() override
static sal_uInt16 impl_GetUInt16(const sal_uInt8 *&pVal)
sal_uInt32 m_nShapeType
Remember the shape type.
long Right() const
#define ESCHER_Prop_AnchorText
NONE
The class that does all the actual RTF export-related work.
Definition: rtfexport.hxx:36
ShapeFlag m_nShapeFlags
Remember the shape flags.
void LeaveGroup() override
#define OOO_STRING_SVTOOLS_RTF_SHPZ
The class that has handlers for various resource types when exporting as RTF.
msopathClientEscape
static bool isTextBox(const SwFrameFormat *pFormat, sal_uInt16 nType)
Is the frame format a text box?
const SfxItemSet & GetParaAttribs(sal_Int32 nPara) const
#define ESCHER_ShpInst_Line
sal_Int32 StartShape()
long Top() const
OString WriteHex(const sal_uInt8 *pData, sal_uInt32 nSize, SvStream *pStream=nullptr, sal_uInt32 nLimit=64)
SwFrameFormat * FindFrameFormat(SdrObject *pObj)
The Get reverse way: seeks the format to the specified object.
Definition: dcontact.cxx:125
RtfAttributeOutput & m_rAttrOutput
#define ESCHER_Prop_fillOpacity
void Commit(EscherPropertyContainer &rProps, const tools::Rectangle &rRect) override
#define OOO_STRING_SVTOOLS_RTF_SP
OUString GetText(sal_Int32 nPara) const
#define ESCHER_Prop_dyTextBottom
#define ESCHER_Prop_fNoLineDrawDash
#define RES_FLYFRMFMT
Definition: hintids.hxx:274
ShapeFlag
#define OOO_STRING_SVTOOLS_RTF_SHPLEFT
#define ESCHER_Prop_lineBackColor
#define DBG_UNHANDLED_EXCEPTION(...)
const EditTextObject & GetTextObject() const
Style of a layout element.
Definition: frmfmt.hxx:57
#define RTF_MULTIPLIER
RtfExport & m_rExport
#define ESCHER_Prop_WrapText
#define OOO_STRING_SVTOOLS_RTF_SHPWR
#define ESCHER_Prop_geoTop
sal_uInt32 EnterGroup(const OUString &rShapeName, const tools::Rectangle *pBoundRect) override
int i
msopathClose
TextTypes
Definition: wrtww8.hxx:161
static void lcl_AppendSP(OStringBuffer &rRunText, const char cName[], const OString &rValue)
void writeTextFrame(const ww8::Frame &rFrame, bool bTextBox=false)
Handles just the { ...} part of a shape export.
long Bottom() const
sal_uInt32 GetOrdNum() const
void AddShape(sal_uInt32 nShapeType, ShapeFlag nShapeFlags, sal_uInt32 nShapeId=0) override
#define OOO_STRING_SVTOOLS_RTF_SHP
#define ESCHER_Prop_FitTextToShape
#define ESCHER_ShpInst_COUNT
#define OOO_STRING_SVTOOLS_RTF_SHPTOP
#define OOO_STRING_SVTOOLS_RTF_PAR
OUString GetName() const
#define ESCHER_Prop_lineJoinStyle
msopathEscape
#define ESCHER_Prop_fillBlip
#define OOO_STRING_SVTOOLS_RTF_SHPINST
OStringBuffer m_aShapeStyle
Remember style, the most important shape attribute ;-)
#define ESCHER_Prop_fillBackColor
std::vector< ISegmentProgressBarRef > aSegments
#define OOO_STRING_SVTOOLS_RTF_PICW
Size GetPrefSize() const
#define ESCHER_Prop_dxTextLeft
void RunText(const OUString &rText, rtl_TextEncoding eCharSet=RTL_TEXTENCODING_UTF8) override
Output text (inside a run).
#define ESCHER_Prop_fillColor
#define ESCHER_Prop_fFillOK
sal_Int32 GetParagraphCount() const
static ErrCode Export(SvStream &rOStm, const Graphic &rGraphic, ConvertDataFormat nFormat)
#define ESCHER_SpContainer
#define OOO_STRING_SVTOOLS_RTF_IGNORE
OString OutString(const OUString &rStr, rtl_TextEncoding eDestEnc, bool bUnicode=true)
virtual void CloseContainer()
#define ESCHER_ShpInst_PictureFrame
#define OOO_STRING_SVTOOLS_RTF_SHPBOTTOM
#define RES_DRAWFRMFMT
Definition: hintids.hxx:277
const SdrObject * m_pSdrObject
void WriteOutliner(const OutlinerParaObject &rParaObj, TextTypes eType)
Write editeng text, e.g. shape or comment.
unsigned char sal_uInt8
ESCHER_WrapByPoints
Make exporting a Writer Frame easy.
#define ESCHER_Prop_lineColor
~RtfSdrExport() override
#define ESCHER_Prop_fNoFillHitTest
bool IsTextAttr(sal_Int32 nSwPos)
Definition: wrtw8esh.cxx:1207
virtual void OpenContainer(sal_uInt16 nEscherContainer, int nRecInstance=0)
msopathMoveTo
#define SAL_INFO(area, stream)
const char * pShapeTypes[]
#define ESCHER_Prop_fillType
#define ESCHER_Prop_adjustValue
ww8::Frames m_aFrames
Definition: wrtww8.hxx:487
void AddLineDimensions(const tools::Rectangle &rRectangle)
Add starting and ending point of a line to the m_pShapeAttrList.
#define ESCHER_Prop_shapePath
long Left() const
#define OOO_STRING_SVTOOLS_RTF_SHPBXIGNORE
sal_uInt32 mnGroupLevel
OStringBuffer & Styles()
void AddSdrObject(const SdrObject &rObj)
Export the sdr object as Sdr.
#define OOO_STRING_SVTOOLS_RTF_SV
#define SAL_WARN(area, stream)
void CloseContainer() override
#define OOO_STRING_SVTOOLS_RTF_SHPTXT
static sal_Int32 impl_GetPointComponent(const sal_uInt8 *&pVal, std::size_t &rVerticesPos, sal_uInt16 nPointSize)
#define OOO_STRING_SVTOOLS_RTF_SHPBYIGNORE
rtl_TextEncoding GetNextCharSet() const
Definition: wrtw8esh.cxx:1053
bool GetOpt(sal_uInt16 nPropertyID, sal_uInt32 &rPropValue) const
std::map< OString, OString > m_aShapeProps
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
aStr
void NextPara(sal_Int32 nPar)
Definition: wrtw8esh.cxx:1033
SVX_DLLPUBLIC css::uno::Reference< css::drawing::XShape > GetXShapeForSdrObject(SdrObject *pObj)
RtfSdrExport(RtfExport &rExport)
#define SAL_NEWLINE_STRING
std::vector< EscherPropSortStruct > EscherProperties
const void * GetData()
void EndShape(sal_Int32 nShapeElement)
void AddRectangleDimensions(OStringBuffer &rBuffer, const tools::Rectangle &rRectangle)
Add position and size to the OStringBuffer.
#define ESCHER_Prop_dxTextRight
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo