fdo#78590: Fix for Corruption of para with framePr & drawing object into para
[LibreOffice.git] / sw / source / filter / ww8 / docxsdrexport.cxx
blob42e9f9cd2abd2abf1e9a87175e9527fb109ac21a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <com/sun/star/drawing/XShape.hpp>
11 #include <com/sun/star/xml/dom/XDocument.hpp>
12 #include <com/sun/star/xml/sax/XSAXSerializable.hpp>
13 #include <com/sun/star/xml/sax/Writer.hpp>
14 #include <editeng/lrspitem.hxx>
15 #include <editeng/ulspitem.hxx>
16 #include <editeng/opaqitem.hxx>
17 #include <editeng/shaditem.hxx>
18 #include <editeng/unoprnms.hxx>
19 #include <editeng/charrotateitem.hxx>
20 #include <svx/svdobj.hxx>
21 #include <svx/svdmodel.hxx>
22 #include <svx/svdogrp.hxx>
23 #include <oox/token/tokens.hxx>
24 #include <oox/export/drawingml.hxx>
25 #include <oox/drawingml/drawingmltypes.hxx>
26 #include <oox/export/utils.hxx>
27 #include <oox/export/vmlexport.hxx>
28 #include <oox/token/properties.hxx>
30 #include <frmatr.hxx>
31 #include <frmfmt.hxx>
32 #include <textboxhelper.hxx>
33 #include <fmtanchr.hxx>
34 #include <fmtornt.hxx>
35 #include <fmtsrnd.hxx>
36 #include <fmtcntnt.hxx>
37 #include <ndtxt.hxx>
38 #include <txatbase.hxx>
39 #include <fmtautofmt.hxx>
40 #include <fmtfsize.hxx>
42 #include <drawdoc.hxx>
43 #include <docxsdrexport.hxx>
44 #include <docxexport.hxx>
45 #include <docxexportfilter.hxx>
46 #include <writerhelper.hxx>
47 #include <comphelper/seqstream.hxx>
50 #include <IDocumentDrawModelAccess.hxx>
52 using namespace com::sun::star;
53 using namespace oox;
55 namespace
58 uno::Sequence<beans::PropertyValue> lclGetProperty(uno::Reference<drawing::XShape> rShape, const OUString& rPropName)
60 uno::Sequence<beans::PropertyValue> aResult;
61 uno::Reference<beans::XPropertySet> xPropertySet(rShape, uno::UNO_QUERY);
62 uno::Reference<beans::XPropertySetInfo> xPropSetInfo;
64 if (!xPropertySet.is())
65 return aResult;
67 xPropSetInfo = xPropertySet->getPropertySetInfo();
68 if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(rPropName))
70 xPropertySet->getPropertyValue(rPropName) >>= aResult;
72 return aResult;
75 OUString lclGetAnchorIdFromGrabBag(const SdrObject* pObj)
77 OUString aResult;
78 uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pObj)->getUnoShape(), uno::UNO_QUERY);
79 OUString aGrabBagName;
80 uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY);
81 if (xServiceInfo->supportsService("com.sun.star.text.TextFrame"))
82 aGrabBagName = "FrameInteropGrabBag";
83 else
84 aGrabBagName = "InteropGrabBag";
85 uno::Sequence< beans::PropertyValue > propList = lclGetProperty(xShape, aGrabBagName);
86 for (sal_Int32 nProp = 0; nProp < propList.getLength(); ++nProp)
88 OUString aPropName = propList[nProp].Name;
89 if (aPropName == "AnchorId")
91 propList[nProp].Value >>= aResult;
92 break;
95 return aResult;
98 void lclMovePositionWithRotation(awt::Point& aPos, const Size& rSize, sal_Int64 nRotation)
100 // code from ImplEESdrWriter::ImplFlipBoundingBox (filter/source/msfilter/eschesdo.cxx)
101 // TODO: refactor
103 if (nRotation == 0)
104 return;
106 if (nRotation < 0)
107 nRotation = (36000 + nRotation) % 36000;
108 if (nRotation % 18000 == 0)
109 nRotation = 0;
110 while (nRotation > 9000)
111 nRotation = (18000 - (nRotation % 18000));
113 double fVal = (double) nRotation * F_PI18000;
114 double fCos = cos(fVal);
115 double fSin = sin(fVal);
117 double nWidthHalf = (double) rSize.Width() / 2;
118 double nHeightHalf = (double) rSize.Height() / 2;
120 double nXDiff = fSin * nHeightHalf + fCos * nWidthHalf - nWidthHalf;
121 double nYDiff = fSin * nWidthHalf + fCos * nHeightHalf - nHeightHalf;
123 aPos.X += nXDiff;
124 aPos.Y += nYDiff;
129 ExportDataSaveRestore::ExportDataSaveRestore(DocxExport& rExport, sal_uLong nStt, sal_uLong nEnd, sw::Frame* pParentFrame)
130 : m_rExport(rExport)
132 m_rExport.SaveData(nStt, nEnd);
133 m_rExport.mpParentFrame = pParentFrame;
136 ExportDataSaveRestore::~ExportDataSaveRestore()
138 m_rExport.RestoreData();
141 /// Holds data used by DocxSdrExport only.
142 struct DocxSdrExport::Impl
144 DocxSdrExport& m_rSdrExport;
145 DocxExport& m_rExport;
146 sax_fastparser::FSHelperPtr m_pSerializer;
147 oox::drawingml::DrawingML* m_pDrawingML;
148 const Size* m_pFlyFrameSize;
149 bool m_bTextFrameSyntax;
150 bool m_bDMLTextFrameSyntax;
151 sax_fastparser::FastAttributeList* m_pFlyAttrList;
152 sax_fastparser::FastAttributeList* m_pTextboxAttrList;
153 OStringBuffer m_aTextFrameStyle;
154 bool m_bFrameBtLr;
155 bool m_bDrawingOpen;
156 bool m_bParagraphHasDrawing; ///Flag for checking drawing in a paragraph.
157 bool m_bFlyFrameGraphic;
158 sax_fastparser::FastAttributeList* m_pFlyFillAttrList;
159 sax_fastparser::FastAttributeList* m_pFlyWrapAttrList;
160 sax_fastparser::FastAttributeList* m_pBodyPrAttrList;
161 sax_fastparser::FastAttributeList* m_pDashLineStyleAttr;
162 sal_Int32 m_nId ;
163 sal_Int32 m_nSeq ;
164 bool m_bDMLAndVMLDrawingOpen;
165 /// List of TextBoxes in this document: they are exported as part of their shape, never alone.
166 std::list<SwFrmFmt*> m_aTextBoxes;
168 Impl(DocxSdrExport& rSdrExport, DocxExport& rExport, sax_fastparser::FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML)
169 : m_rSdrExport(rSdrExport),
170 m_rExport(rExport),
171 m_pSerializer(pSerializer),
172 m_pDrawingML(pDrawingML),
173 m_pFlyFrameSize(0),
174 m_bTextFrameSyntax(false),
175 m_bDMLTextFrameSyntax(false),
176 m_pFlyAttrList(0),
177 m_pTextboxAttrList(0),
178 m_bFrameBtLr(false),
179 m_bDrawingOpen(false),
180 m_bParagraphHasDrawing(false),
181 m_bFlyFrameGraphic(false),
182 m_pFlyFillAttrList(0),
183 m_pFlyWrapAttrList(0),
184 m_pBodyPrAttrList(0),
185 m_pDashLineStyleAttr(0),
186 m_nId(0),
187 m_nSeq(0),
188 m_bDMLAndVMLDrawingOpen(false),
189 m_aTextBoxes(SwTextBoxHelper::findTextBoxes(m_rExport.pDoc))
193 ~Impl()
195 delete m_pFlyAttrList, m_pFlyAttrList = NULL;
196 delete m_pTextboxAttrList, m_pTextboxAttrList = NULL;
199 /// Writes wp wrapper code around an SdrObject, which itself is written using drawingML syntax.
201 void textFrameShadow(const SwFrmFmt& rFrmFmt);
202 bool isSupportedDMLShape(com::sun::star::uno::Reference<com::sun::star::drawing::XShape> xShape);
205 DocxSdrExport::DocxSdrExport(DocxExport& rExport, sax_fastparser::FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML)
206 : m_pImpl(new Impl(*this, rExport, pSerializer, pDrawingML))
210 DocxSdrExport::~DocxSdrExport()
214 void DocxSdrExport::setSerializer(sax_fastparser::FSHelperPtr pSerializer)
216 m_pImpl->m_pSerializer = pSerializer;
219 const Size* DocxSdrExport::getFlyFrameSize()
221 return m_pImpl->m_pFlyFrameSize;
224 bool DocxSdrExport::getTextFrameSyntax()
226 return m_pImpl->m_bTextFrameSyntax;
229 bool DocxSdrExport::getDMLTextFrameSyntax()
231 return m_pImpl->m_bDMLTextFrameSyntax;
234 sax_fastparser::FastAttributeList*& DocxSdrExport::getFlyAttrList()
236 return m_pImpl->m_pFlyAttrList;
239 void DocxSdrExport::setFlyAttrList(sax_fastparser::FastAttributeList* pAttrList)
241 m_pImpl->m_pFlyAttrList = pAttrList;
244 sax_fastparser::FastAttributeList* DocxSdrExport::getTextboxAttrList()
246 return m_pImpl->m_pTextboxAttrList;
249 OStringBuffer& DocxSdrExport::getTextFrameStyle()
251 return m_pImpl->m_aTextFrameStyle;
254 bool DocxSdrExport::getFrameBtLr()
256 return m_pImpl->m_bFrameBtLr;
259 bool DocxSdrExport::IsDrawingOpen()
261 return m_pImpl->m_bDrawingOpen;
264 bool DocxSdrExport::IsDMLAndVMLDrawingOpen()
266 return m_pImpl->m_bDMLAndVMLDrawingOpen;
269 bool DocxSdrExport::IsParagraphHasDrawing()
271 return m_pImpl->m_bParagraphHasDrawing;
274 void DocxSdrExport::setParagraphHasDrawing(bool bParagraphHasDrawing)
276 m_pImpl->m_bParagraphHasDrawing = bParagraphHasDrawing;
279 sax_fastparser::FastAttributeList*& DocxSdrExport::getFlyFillAttrList()
281 return m_pImpl->m_pFlyFillAttrList;
284 sax_fastparser::FastAttributeList* DocxSdrExport::getFlyWrapAttrList()
286 return m_pImpl->m_pFlyWrapAttrList;
289 sax_fastparser::FastAttributeList* DocxSdrExport::getBodyPrAttrList()
291 return m_pImpl->m_pBodyPrAttrList;
294 sax_fastparser::FastAttributeList*& DocxSdrExport::getDashLineStyle()
296 return m_pImpl->m_pDashLineStyleAttr;
299 void DocxSdrExport::setFlyWrapAttrList(sax_fastparser::FastAttributeList* pAttrList)
301 m_pImpl->m_pFlyWrapAttrList = pAttrList;
304 void DocxSdrExport::startDMLAnchorInline(const SwFrmFmt* pFrmFmt, const Size& rSize)
306 m_pImpl->m_bDrawingOpen = true;
307 m_pImpl->m_bParagraphHasDrawing = true;
308 m_pImpl->m_pSerializer->startElementNS(XML_w, XML_drawing, FSEND);
310 const SvxLRSpaceItem pLRSpaceItem = pFrmFmt->GetLRSpace(false);
311 const SvxULSpaceItem pULSpaceItem = pFrmFmt->GetULSpace(false);
313 bool isAnchor;
315 if (m_pImpl->m_bFlyFrameGraphic)
317 isAnchor = false; // make Graphic object inside DMLTextFrame & VMLTextFrame as Inline
319 else
321 isAnchor = pFrmFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR;
323 if (isAnchor)
325 sax_fastparser::FastAttributeList* attrList = m_pImpl->m_pSerializer->createAttrList();
326 bool bOpaque = pFrmFmt->GetOpaque().GetValue();
327 awt::Point aPos(pFrmFmt->GetHoriOrient().GetPos(), pFrmFmt->GetVertOrient().GetPos());
328 const SdrObject* pObj = pFrmFmt->FindRealSdrObject();
329 if (pObj != NULL)
331 // SdrObjects know their layer, consider that instead of the frame format.
332 bOpaque = pObj->GetLayer() != pFrmFmt->GetDoc()->getIDocumentDrawModelAccess().GetHellId() && pObj->GetLayer() != pFrmFmt->GetDoc()->getIDocumentDrawModelAccess().GetInvisibleHellId();
334 lclMovePositionWithRotation(aPos, rSize, pObj->GetRotateAngle());
336 attrList->add(XML_behindDoc, bOpaque ? "0" : "1");
337 attrList->add(XML_distT, OString::number(TwipsToEMU(pULSpaceItem.GetUpper())).getStr());
338 attrList->add(XML_distB, OString::number(TwipsToEMU(pULSpaceItem.GetLower())).getStr());
339 attrList->add(XML_distL, OString::number(TwipsToEMU(pLRSpaceItem.GetLeft())).getStr());
340 attrList->add(XML_distR, OString::number(TwipsToEMU(pLRSpaceItem.GetRight())).getStr());
341 attrList->add(XML_simplePos, "0");
342 attrList->add(XML_locked, "0");
343 attrList->add(XML_layoutInCell, "1");
344 attrList->add(XML_allowOverlap, "1"); // TODO
345 if (pObj != NULL)
346 // It seems 0 and 1 have special meaning: just start counting from 2 to avoid issues with that.
347 attrList->add(XML_relativeHeight, OString::number(pObj->GetOrdNum() + 2));
348 else
349 // relativeHeight is mandatory attribute, if value is not present, we must write default value
350 attrList->add(XML_relativeHeight, "0");
351 if (pObj != NULL)
353 OUString sAnchorId = lclGetAnchorIdFromGrabBag(pObj);
354 if (!sAnchorId.isEmpty())
355 attrList->addNS(XML_wp14, XML_anchorId, OUStringToOString(sAnchorId, RTL_TEXTENCODING_UTF8));
357 sax_fastparser::XFastAttributeListRef xAttrList(attrList);
358 m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_anchor, xAttrList);
359 m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_simplePos, XML_x, "0", XML_y, "0", FSEND); // required, unused
360 const char* relativeFromH;
361 const char* relativeFromV;
362 const char* alignH = NULL;
363 const char* alignV = NULL;
364 switch (pFrmFmt->GetVertOrient().GetRelationOrient())
366 case text::RelOrientation::PAGE_PRINT_AREA:
367 relativeFromV = "margin";
368 break;
369 case text::RelOrientation::PAGE_FRAME:
370 relativeFromV = "page";
371 break;
372 case text::RelOrientation::FRAME:
373 relativeFromV = "paragraph";
374 break;
375 case text::RelOrientation::TEXT_LINE:
376 default:
377 relativeFromV = "line";
378 break;
380 switch (pFrmFmt->GetVertOrient().GetVertOrient())
382 case text::VertOrientation::TOP:
383 case text::VertOrientation::CHAR_TOP:
384 case text::VertOrientation::LINE_TOP:
385 if (pFrmFmt->GetVertOrient().GetRelationOrient() == text::RelOrientation::TEXT_LINE)
386 alignV = "bottom";
387 else
388 alignV = "top";
389 break;
390 case text::VertOrientation::BOTTOM:
391 case text::VertOrientation::CHAR_BOTTOM:
392 case text::VertOrientation::LINE_BOTTOM:
393 if (pFrmFmt->GetVertOrient().GetRelationOrient() == text::RelOrientation::TEXT_LINE)
394 alignV = "top";
395 else
396 alignV = "bottom";
397 break;
398 case text::VertOrientation::CENTER:
399 case text::VertOrientation::CHAR_CENTER:
400 case text::VertOrientation::LINE_CENTER:
401 alignV = "center";
402 break;
403 default:
404 break;
406 switch (pFrmFmt->GetHoriOrient().GetRelationOrient())
408 case text::RelOrientation::PAGE_PRINT_AREA:
409 relativeFromH = "margin";
410 break;
411 case text::RelOrientation::PAGE_FRAME:
412 relativeFromH = "page";
413 break;
414 case text::RelOrientation::CHAR:
415 relativeFromH = "character";
416 break;
417 case text::RelOrientation::PAGE_RIGHT:
418 relativeFromH = "page";
419 alignH = "right";
420 break;
421 case text::RelOrientation::FRAME:
422 default:
423 relativeFromH = "column";
424 break;
426 switch (pFrmFmt->GetHoriOrient().GetHoriOrient())
428 case text::HoriOrientation::LEFT:
429 alignH = "left";
430 break;
431 case text::HoriOrientation::RIGHT:
432 alignH = "right";
433 break;
434 case text::HoriOrientation::CENTER:
435 alignH = "center";
436 break;
437 case text::HoriOrientation::INSIDE:
438 alignH = "inside";
439 break;
440 case text::HoriOrientation::OUTSIDE:
441 alignH = "outside";
442 break;
443 default:
444 break;
446 m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_positionH, XML_relativeFrom, relativeFromH, FSEND);
448 * Sizes of integral types
449 * climits header defines constants with the limits of integral types for the specific system and compiler implemetation used.
450 * Use of this might cause platform dependent problem like posOffset exceed the limit.
452 const sal_Int64 MAX_INTEGER_VALUE = SAL_MAX_INT32;
453 const sal_Int64 MIN_INTEGER_VALUE = SAL_MIN_INT32;
454 if (alignH != NULL)
456 m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_align, FSEND);
457 m_pImpl->m_pSerializer->write(alignH);
458 m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_align);
460 else
462 m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_posOffset, FSEND);
463 sal_Int64 nTwipstoEMU = TwipsToEMU(aPos.X);
465 /* Absolute Position Offset Value is of type Int. Hence it should not be greater than
466 * Maximum value for Int OR Less than the Minimum value for Int.
467 * - Maximum value for Int = 2147483647
468 * - Minimum value for Int = -2147483648
470 * As per ECMA Specification : ECMA-376, Second Edition,
471 * Part 1 - Fundamentals And Markup Language Reference[20.4.3.3 ST_PositionOffset (Absolute Position Offset Value)]
473 * Please refer : http://www.schemacentral.com/sc/xsd/t-xsd_int.html
476 if (nTwipstoEMU > MAX_INTEGER_VALUE)
478 nTwipstoEMU = MAX_INTEGER_VALUE;
480 else if (nTwipstoEMU < MIN_INTEGER_VALUE)
482 nTwipstoEMU = MIN_INTEGER_VALUE;
484 m_pImpl->m_pSerializer->write(nTwipstoEMU);
485 m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_posOffset);
487 m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_positionH);
488 m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_positionV, XML_relativeFrom, relativeFromV, FSEND);
489 if (alignV != NULL)
491 m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_align, FSEND);
492 m_pImpl->m_pSerializer->write(alignV);
493 m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_align);
495 else
497 m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_posOffset, FSEND);
498 sal_Int64 nTwipstoEMU = TwipsToEMU(aPos.Y);
499 if (nTwipstoEMU > MAX_INTEGER_VALUE)
501 nTwipstoEMU = MAX_INTEGER_VALUE;
503 else if (nTwipstoEMU < MIN_INTEGER_VALUE)
505 nTwipstoEMU = MIN_INTEGER_VALUE;
507 m_pImpl->m_pSerializer->write(nTwipstoEMU);
508 m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_posOffset);
510 m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_positionV);
512 else
514 sax_fastparser::FastAttributeList* aAttrList = m_pImpl->m_pSerializer->createAttrList();
515 aAttrList->add(XML_distT, OString::number(TwipsToEMU(pULSpaceItem.GetUpper())).getStr());
516 aAttrList->add(XML_distB, OString::number(TwipsToEMU(pULSpaceItem.GetLower())).getStr());
517 aAttrList->add(XML_distL, OString::number(TwipsToEMU(pLRSpaceItem.GetLeft())).getStr());
518 aAttrList->add(XML_distR, OString::number(TwipsToEMU(pLRSpaceItem.GetRight())).getStr());
519 const SdrObject* pObj = pFrmFmt->FindRealSdrObject();
520 if (pObj != NULL)
522 OUString sAnchorId = lclGetAnchorIdFromGrabBag(pObj);
523 if (!sAnchorId.isEmpty())
524 aAttrList->addNS(XML_wp14, XML_anchorId, OUStringToOString(sAnchorId, RTL_TEXTENCODING_UTF8));
526 m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_inline, aAttrList);
529 // now the common parts
530 // extent of the image
532 * Extent width is of type long ( i.e cx & cy ) as
534 * per ECMA-376, Second Edition, Part 1 - Fundamentals And Markup Language Reference
535 * [ 20.4.2.7 extent (Drawing Object Size)]
537 * cy is of type a:ST_PositiveCoordinate.
538 * Minimum inclusive: 0
539 * Maximum inclusive: 27273042316900
541 * reference : http://www.schemacentral.com/sc/ooxml/e-wp_extent-1.html
543 * Though ECMA mentions the max value as aforementioned. It appears that MSO does not
544 * handle for the same, infact it acutally can handles a max value of int32 i.e
545 * 2147483647( MAX_INTEGER_VALUE ).
546 * Therefore changing the following accordingly so that LO sync's up with MSO.
548 sal_uInt64 cx = 0 ;
549 sal_uInt64 cy = 0 ;
550 const sal_Int64 MAX_INTEGER_VALUE = SAL_MAX_INT32;
552 // the 'Size' type uses 'long' for width and height, so on
553 // platforms where 'long' is 32 bits they can obviously never be
554 // larger than the max signed 32-bit integer.
555 #if SAL_TYPES_SIZEOFLONG > 4
556 if (rSize.Width() > MAX_INTEGER_VALUE)
557 cx = MAX_INTEGER_VALUE ;
558 else
559 #endif
561 if (0 > rSize.Width())
562 cx = 0 ;
563 else
564 cx = rSize.Width();
567 #if SAL_TYPES_SIZEOFLONG > 4
568 if (rSize.Height() > MAX_INTEGER_VALUE)
569 cy = MAX_INTEGER_VALUE ;
570 else
571 #endif
573 if (0 > rSize.Height())
574 cy = 0 ;
575 else
576 cy = rSize.Height();
579 OString aWidth(OString::number(TwipsToEMU(cx)));
580 //we explicitly check the converted EMU value for the range as mentioned in above comment.
581 aWidth = (aWidth.toInt64() > 0 ? (aWidth.toInt64() > MAX_INTEGER_VALUE ? I64S(MAX_INTEGER_VALUE) : aWidth.getStr()): "0");
582 OString aHeight(OString::number(TwipsToEMU(cy)));
583 aHeight = (aHeight.toInt64() > 0 ? (aHeight.toInt64() > MAX_INTEGER_VALUE ? I64S(MAX_INTEGER_VALUE) : aHeight.getStr()): "0");
585 m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_extent,
586 XML_cx, aWidth,
587 XML_cy, aHeight,
588 FSEND);
590 // effectExtent, extent including the effect (shadow only for now)
591 SvxShadowItem aShadowItem = pFrmFmt->GetShadow();
592 OString aLeftExt("0"), aRightExt("0"), aTopExt("0"), aBottomExt("0");
593 if (aShadowItem.GetLocation() != SVX_SHADOW_NONE)
595 OString aShadowWidth(OString::number(TwipsToEMU(aShadowItem.GetWidth())));
596 switch (aShadowItem.GetLocation())
598 case SVX_SHADOW_TOPLEFT:
599 aTopExt = aLeftExt = aShadowWidth;
600 break;
601 case SVX_SHADOW_TOPRIGHT:
602 aTopExt = aRightExt = aShadowWidth;
603 break;
604 case SVX_SHADOW_BOTTOMLEFT:
605 aBottomExt = aLeftExt = aShadowWidth;
606 break;
607 case SVX_SHADOW_BOTTOMRIGHT:
608 aBottomExt = aRightExt = aShadowWidth;
609 break;
610 case SVX_SHADOW_NONE:
611 case SVX_SHADOW_END:
612 break;
616 m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_effectExtent,
617 XML_l, aLeftExt,
618 XML_t, aTopExt,
619 XML_r, aRightExt,
620 XML_b, aBottomExt,
621 FSEND);
623 if (isAnchor)
625 switch (pFrmFmt->GetSurround().GetValue())
627 case SURROUND_NONE:
628 m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_wrapTopAndBottom, FSEND);
629 break;
630 case SURROUND_THROUGHT:
631 m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_wrapNone, FSEND);
632 break;
633 case SURROUND_PARALLEL:
634 m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_wrapSquare,
635 XML_wrapText, "bothSides", FSEND);
636 break;
637 case SURROUND_IDEAL:
638 default:
639 m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_wrapSquare,
640 XML_wrapText, "largest", FSEND);
641 break;
646 void DocxSdrExport::endDMLAnchorInline(const SwFrmFmt* pFrmFmt)
648 bool isAnchor;
649 if (m_pImpl->m_bFlyFrameGraphic)
651 isAnchor = false; // end Inline Graphic object inside DMLTextFrame
653 else
655 isAnchor = pFrmFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR;
657 m_pImpl->m_pSerializer->endElementNS(XML_wp, isAnchor ? XML_anchor : XML_inline);
659 m_pImpl->m_pSerializer->endElementNS(XML_w, XML_drawing);
660 m_pImpl->m_bDrawingOpen = false;
663 void DocxSdrExport::writeVMLDrawing(const SdrObject* sdrObj, const SwFrmFmt& rFrmFmt,const Point& rNdTopLeft)
665 bool bSwapInPage = false;
666 if (!(sdrObj)->GetPage())
668 if (SdrModel* pModel = m_pImpl->m_rExport.pDoc->getIDocumentDrawModelAccess().GetDrawModel())
670 if (SdrPage* pPage = pModel->GetPage(0))
672 bSwapInPage = true;
673 const_cast< SdrObject* >(sdrObj)->SetPage(pPage);
678 m_pImpl->m_pSerializer->startElementNS(XML_w, XML_pict, FSEND);
679 m_pImpl->m_pDrawingML->SetFS(m_pImpl->m_pSerializer);
680 // See WinwordAnchoring::SetAnchoring(), these are not part of the SdrObject, have to be passed around manually.
682 SwFmtHoriOrient rHoriOri = (rFrmFmt).GetHoriOrient();
683 SwFmtVertOrient rVertOri = (rFrmFmt).GetVertOrient();
684 m_pImpl->m_rExport.VMLExporter().AddSdrObject(*(sdrObj),
685 rHoriOri.GetHoriOrient(), rVertOri.GetVertOrient(),
686 rHoriOri.GetRelationOrient(),
687 rVertOri.GetRelationOrient(), (&rNdTopLeft), true);
688 m_pImpl->m_pSerializer->endElementNS(XML_w, XML_pict);
690 if (bSwapInPage)
691 const_cast< SdrObject* >(sdrObj)->SetPage(0);
694 bool lcl_isLockedCanvas(uno::Reference<drawing::XShape> xShape)
696 bool bRet = false;
697 uno::Sequence< beans::PropertyValue > propList =
698 lclGetProperty(xShape, "InteropGrabBag");
699 for (sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp)
701 OUString propName = propList[nProp].Name;
702 if (propName == "LockedCanvas")
705 * Export as Locked Canvas only if the property
706 * is in the PropertySet
708 bRet = true;
709 break;
712 return bRet;
715 void DocxSdrExport::writeDMLDrawing(const SdrObject* pSdrObject, const SwFrmFmt* pFrmFmt, int nAnchorId)
717 uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pSdrObject)->getUnoShape(), uno::UNO_QUERY_THROW);
718 if (!m_pImpl->isSupportedDMLShape(xShape))
719 return;
721 sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer;
722 Size aSize(pSdrObject->GetLogicRect().GetWidth(), pSdrObject->GetLogicRect().GetHeight());
723 startDMLAnchorInline(pFrmFmt, aSize);
725 sax_fastparser::FastAttributeList* pDocPrAttrList = pFS->createAttrList();
726 pDocPrAttrList->add(XML_id, OString::number(nAnchorId).getStr());
727 pDocPrAttrList->add(XML_name, OUStringToOString(pSdrObject->GetName(), RTL_TEXTENCODING_UTF8));
728 if (!pSdrObject->GetTitle().isEmpty())
729 pDocPrAttrList->add(XML_title, OUStringToOString(pSdrObject->GetTitle(), RTL_TEXTENCODING_UTF8));
730 if (!pSdrObject->GetDescription().isEmpty())
731 pDocPrAttrList->add(XML_descr, OUStringToOString(pSdrObject->GetDescription(), RTL_TEXTENCODING_UTF8));
732 sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList);
733 pFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef);
735 uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY_THROW);
736 const char* pNamespace = "http://schemas.microsoft.com/office/word/2010/wordprocessingShape";
737 if (xServiceInfo->supportsService("com.sun.star.drawing.GroupShape"))
738 pNamespace = "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup";
739 else if (xServiceInfo->supportsService("com.sun.star.drawing.GraphicObjectShape"))
740 pNamespace = "http://schemas.openxmlformats.org/drawingml/2006/picture";
741 pFS->startElementNS(XML_a, XML_graphic,
742 FSNS(XML_xmlns, XML_a), "http://schemas.openxmlformats.org/drawingml/2006/main",
743 FSEND);
744 pFS->startElementNS(XML_a, XML_graphicData,
745 XML_uri, pNamespace,
746 FSEND);
748 bool bLockedCanvas = lcl_isLockedCanvas(xShape);
749 if (bLockedCanvas)
750 pFS->startElementNS(XML_lc, XML_lockedCanvas,
751 FSNS(XML_xmlns, XML_lc), "http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas",
752 FSEND);
754 m_pImpl->m_rExport.OutputDML(xShape);
756 if (bLockedCanvas)
757 pFS->endElementNS(XML_lc, XML_lockedCanvas);
758 pFS->endElementNS(XML_a, XML_graphicData);
759 pFS->endElementNS(XML_a, XML_graphic);
761 // Relative size of the drawing.
762 if (pSdrObject->GetRelativeWidth())
764 // At the moment drawinglayer objects are always relative from page.
765 pFS->startElementNS(XML_wp14, XML_sizeRelH,
766 XML_relativeFrom, (pSdrObject->GetRelativeWidthRelation() == text::RelOrientation::FRAME ? "margin" : "page"),
767 FSEND);
768 pFS->startElementNS(XML_wp14, XML_pctWidth, FSEND);
769 pFS->writeEscaped(OUString::number(*pSdrObject->GetRelativeWidth() * 100 * oox::drawingml::PER_PERCENT));
770 pFS->endElementNS(XML_wp14, XML_pctWidth);
771 pFS->endElementNS(XML_wp14, XML_sizeRelH);
773 if (pSdrObject->GetRelativeHeight())
775 pFS->startElementNS(XML_wp14, XML_sizeRelV,
776 XML_relativeFrom, (pSdrObject->GetRelativeHeightRelation() == text::RelOrientation::FRAME ? "margin" : "page"),
777 FSEND);
778 pFS->startElementNS(XML_wp14, XML_pctHeight, FSEND);
779 pFS->writeEscaped(OUString::number(*pSdrObject->GetRelativeHeight() * 100 * oox::drawingml::PER_PERCENT));
780 pFS->endElementNS(XML_wp14, XML_pctHeight);
781 pFS->endElementNS(XML_wp14, XML_sizeRelV);
784 endDMLAnchorInline(pFrmFmt);
787 void DocxSdrExport::Impl::textFrameShadow(const SwFrmFmt& rFrmFmt)
789 SvxShadowItem aShadowItem = rFrmFmt.GetShadow();
790 if (aShadowItem.GetLocation() == SVX_SHADOW_NONE)
791 return;
793 OString aShadowWidth(OString::number(double(aShadowItem.GetWidth()) / 20) + "pt");
794 OString aOffset;
795 switch (aShadowItem.GetLocation())
797 case SVX_SHADOW_TOPLEFT:
798 aOffset = "-" + aShadowWidth + ",-" + aShadowWidth;
799 break;
800 case SVX_SHADOW_TOPRIGHT:
801 aOffset = aShadowWidth + ",-" + aShadowWidth;
802 break;
803 case SVX_SHADOW_BOTTOMLEFT:
804 aOffset = "-" + aShadowWidth + "," + aShadowWidth;
805 break;
806 case SVX_SHADOW_BOTTOMRIGHT:
807 aOffset = aShadowWidth + "," + aShadowWidth;
808 break;
809 case SVX_SHADOW_NONE:
810 case SVX_SHADOW_END:
811 break;
813 if (aOffset.isEmpty())
814 return;
816 OString aShadowColor = msfilter::util::ConvertColor(aShadowItem.GetColor());
817 m_pSerializer->singleElementNS(XML_v, XML_shadow,
818 XML_on, "t",
819 XML_color, "#" + aShadowColor,
820 XML_offset, aOffset,
821 FSEND);
824 bool DocxSdrExport::Impl::isSupportedDMLShape(uno::Reference<drawing::XShape> xShape)
826 bool supported = true;
828 uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY_THROW);
829 if (xServiceInfo->supportsService("com.sun.star.drawing.PolyPolygonShape") || xServiceInfo->supportsService("com.sun.star.drawing.PolyLineShape"))
830 supported = false;
832 return supported;
835 void DocxSdrExport::writeDMLAndVMLDrawing(const SdrObject* sdrObj, const SwFrmFmt& rFrmFmt,const Point& rNdTopLeft, int nAnchorId)
837 bool bDMLAndVMLDrawingOpen = m_pImpl->m_bDMLAndVMLDrawingOpen;
838 m_pImpl->m_bDMLAndVMLDrawingOpen = true;
840 // Depending on the shape type, we actually don't write the shape as DML.
841 OUString sShapeType;
842 sal_uInt32 nMirrorFlags = 0;
843 uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(sdrObj)->getUnoShape(), uno::UNO_QUERY_THROW);
845 // Locked canvas is OK inside DML.
846 if (lcl_isLockedCanvas(xShape))
847 bDMLAndVMLDrawingOpen = false;
849 MSO_SPT eShapeType = EscherPropertyContainer::GetCustomShapeType(xShape, nMirrorFlags, sShapeType);
851 // In case we are already inside a DML block, then write the shape only as VML, turn out that's allowed to do.
852 if (eShapeType != ESCHER_ShpInst_TextPlainText && m_pImpl->isSupportedDMLShape(xShape) && !bDMLAndVMLDrawingOpen)
854 m_pImpl->m_pSerializer->startElementNS(XML_mc, XML_AlternateContent, FSEND);
856 const SdrObjGroup* pObjGroup = dynamic_cast<const SdrObjGroup*>(sdrObj);
857 m_pImpl->m_pSerializer->startElementNS(XML_mc, XML_Choice,
858 XML_Requires, (pObjGroup ? "wpg" : "wps"),
859 FSEND);
860 writeDMLDrawing(sdrObj, &rFrmFmt, nAnchorId);
861 m_pImpl->m_pSerializer->endElementNS(XML_mc, XML_Choice);
863 m_pImpl->m_pSerializer->startElementNS(XML_mc, XML_Fallback, FSEND);
864 writeVMLDrawing(sdrObj, rFrmFmt, rNdTopLeft);
865 m_pImpl->m_pSerializer->endElementNS(XML_mc, XML_Fallback);
867 m_pImpl->m_pSerializer->endElementNS(XML_mc, XML_AlternateContent);
869 else
870 writeVMLDrawing(sdrObj, rFrmFmt, rNdTopLeft);
872 m_pImpl->m_bDMLAndVMLDrawingOpen = false;
875 // Converts ARGB transparency (0..255) to drawingml alpha (opposite, and 0..100000)
876 OString lcl_ConvertTransparency(const Color& rColor)
878 if (rColor.GetTransparency() > 0)
880 sal_Int32 nTransparencyPercent = 100 - float(rColor.GetTransparency()) / 2.55;
881 return OString::number(nTransparencyPercent * oox::drawingml::PER_PERCENT);
883 else
884 return OString("");
887 void DocxSdrExport::writeDMLEffectLst(const SwFrmFmt& rFrmFmt)
889 SvxShadowItem aShadowItem = rFrmFmt.GetShadow();
891 // Output effects
892 if (aShadowItem.GetLocation() != SVX_SHADOW_NONE)
894 // Distance is measured diagonally from corner
895 double nShadowDist = sqrt((double)aShadowItem.GetWidth()*aShadowItem.GetWidth()*2.0);
896 OString aShadowDist(OString::number(TwipsToEMU(nShadowDist)));
897 OString aShadowColor = msfilter::util::ConvertColor(aShadowItem.GetColor());
898 OString aShadowAlpha = lcl_ConvertTransparency(aShadowItem.GetColor());
899 sal_uInt32 nShadowDir = 0;
900 switch (aShadowItem.GetLocation())
902 case SVX_SHADOW_TOPLEFT:
903 nShadowDir = 13500000;
904 break;
905 case SVX_SHADOW_TOPRIGHT:
906 nShadowDir = 18900000;
907 break;
908 case SVX_SHADOW_BOTTOMLEFT:
909 nShadowDir = 8100000;
910 break;
911 case SVX_SHADOW_BOTTOMRIGHT:
912 nShadowDir = 2700000;
913 break;
914 case SVX_SHADOW_NONE:
915 case SVX_SHADOW_END:
916 break;
918 OString aShadowDir(OString::number(nShadowDir));
920 m_pImpl->m_pSerializer->startElementNS(XML_a, XML_effectLst, FSEND);
921 m_pImpl->m_pSerializer->startElementNS(XML_a, XML_outerShdw,
922 XML_dist, aShadowDist.getStr(),
923 XML_dir, aShadowDir.getStr(), FSEND);
924 if (aShadowAlpha.isEmpty())
925 m_pImpl->m_pSerializer->singleElementNS(XML_a, XML_srgbClr,
926 XML_val, aShadowColor.getStr(), FSEND);
927 else
929 m_pImpl->m_pSerializer->startElementNS(XML_a, XML_srgbClr, XML_val, aShadowColor.getStr(), FSEND);
930 m_pImpl->m_pSerializer->singleElementNS(XML_a, XML_alpha, XML_val, aShadowAlpha.getStr(), FSEND);
931 m_pImpl->m_pSerializer->endElementNS(XML_a, XML_srgbClr);
933 m_pImpl->m_pSerializer->endElementNS(XML_a, XML_outerShdw);
934 m_pImpl->m_pSerializer->endElementNS(XML_a, XML_effectLst);
939 void DocxSdrExport::writeDiagramRels(uno::Reference<xml::dom::XDocument> xDom,
940 const uno::Sequence< uno::Sequence< uno::Any > >& xRelSeq,
941 uno::Reference< io::XOutputStream > xOutStream, const OUString& sGrabBagProperyName,
942 int nAnchorId)
944 // add image relationships of OOXData, OOXDiagram
945 OUString sType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
946 uno::Reference< xml::sax::XSAXSerializable > xSerializer(xDom, uno::UNO_QUERY);
947 uno::Reference< xml::sax::XWriter > xWriter = xml::sax::Writer::create(comphelper::getProcessComponentContext());
948 xWriter->setOutputStream(xOutStream);
950 // retrieve the relationships from Sequence
951 for (sal_Int32 j = 0; j < xRelSeq.getLength(); j++)
953 // diagramDataRelTuple[0] => RID,
954 // diagramDataRelTuple[1] => xInputStream
955 // diagramDataRelTuple[2] => extension
956 uno::Sequence< uno::Any > diagramDataRelTuple = xRelSeq[j];
958 OUString sRelId, sExtension;
959 diagramDataRelTuple[0] >>= sRelId;
960 diagramDataRelTuple[2] >>= sExtension;
961 OUString sContentType;
962 if (sExtension.equalsIgnoreAsciiCase(".WMF"))
963 sContentType = "image/x-wmf";
964 else
965 sContentType = OUString("image/") + sExtension.copy(1);
966 sRelId = sRelId.copy(3);
968 StreamDataSequence dataSeq;
969 diagramDataRelTuple[1] >>= dataSeq;
970 uno::Reference<io::XInputStream> dataImagebin(new ::comphelper::SequenceInputStream(dataSeq));
972 OUString sFragment("../media/");
973 //nAnchorId is used to make the name unique irrespective of the number of smart arts.
974 sFragment += sGrabBagProperyName + OUString::number(nAnchorId) + "_" + OUString::number(j) + sExtension;
976 PropertySet aProps(xOutStream);
977 aProps.setAnyProperty(PROP_RelId, uno::makeAny(sal_Int32(sRelId.toInt32())));
979 m_pImpl->m_rExport.GetFilter().addRelation(xOutStream, sType, sFragment);
981 sFragment = sFragment.replaceFirst("..","word");
982 uno::Reference< io::XOutputStream > xBinOutStream = m_pImpl->m_rExport.GetFilter().openFragmentStream(sFragment, sContentType);
986 sal_Int32 nBufferSize = 512;
987 uno::Sequence< sal_Int8 > aDataBuffer(nBufferSize);
988 sal_Int32 nRead;
991 nRead = dataImagebin->readBytes(aDataBuffer, nBufferSize);
992 if (nRead)
994 if (nRead < nBufferSize)
996 nBufferSize = nRead;
997 aDataBuffer.realloc(nRead);
999 xBinOutStream->writeBytes(aDataBuffer);
1002 while (nRead);
1003 xBinOutStream->flush();
1005 catch (const uno::Exception& rException)
1007 SAL_WARN("sw.ww8", "DocxSdrExport::writeDiagramRels Failed to copy grabbaged Image: " << rException.Message);
1009 dataImagebin->closeInput();
1013 void DocxSdrExport::writeDiagram(const SdrObject* sdrObject, const SwFrmFmt& rFrmFmt, int nAnchorId)
1015 sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer;
1016 uno::Reference< drawing::XShape > xShape(((SdrObject*)sdrObject)->getUnoShape(), uno::UNO_QUERY);
1017 uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
1019 uno::Reference<xml::dom::XDocument> dataDom;
1020 uno::Reference<xml::dom::XDocument> layoutDom;
1021 uno::Reference<xml::dom::XDocument> styleDom;
1022 uno::Reference<xml::dom::XDocument> colorDom;
1023 uno::Reference<xml::dom::XDocument> drawingDom;
1024 uno::Sequence< uno::Sequence< uno::Any > > xDataRelSeq;
1025 uno::Sequence< uno::Any > diagramDrawing;
1027 // retrieve the doms from the GrabBag
1028 OUString pName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
1029 uno::Sequence< beans::PropertyValue > propList;
1030 xPropSet->getPropertyValue(pName) >>= propList;
1031 for (sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp)
1033 OUString propName = propList[nProp].Name;
1034 if (propName == "OOXData")
1035 propList[nProp].Value >>= dataDom;
1036 else if (propName == "OOXLayout")
1037 propList[nProp].Value >>= layoutDom;
1038 else if (propName == "OOXStyle")
1039 propList[nProp].Value >>= styleDom;
1040 else if (propName == "OOXColor")
1041 propList[nProp].Value >>= colorDom;
1042 else if (propName == "OOXDrawing")
1044 propList[nProp].Value >>= diagramDrawing;
1045 diagramDrawing[0] >>= drawingDom; // if there is OOXDrawing property then set drawingDom here only.
1047 else if (propName == "OOXDiagramDataRels")
1048 propList[nProp].Value >>= xDataRelSeq;
1051 // check that we have the 4 mandatory XDocuments
1052 // if not, there was an error importing and we won't output anything
1053 if (!dataDom.is() || !layoutDom.is() || !styleDom.is() || !colorDom.is())
1054 return;
1056 // write necessary tags to document.xml
1057 Size aSize(sdrObject->GetSnapRect().GetWidth(), sdrObject->GetSnapRect().GetHeight());
1058 startDMLAnchorInline(&rFrmFmt, aSize);
1060 // generate an unique id
1061 sax_fastparser::FastAttributeList* pDocPrAttrList = pFS->createAttrList();
1062 pDocPrAttrList->add(XML_id, OString::number(nAnchorId).getStr());
1063 OUString sName = "Diagram" + OUString::number(nAnchorId);
1064 pDocPrAttrList->add(XML_name, OUStringToOString(sName, RTL_TEXTENCODING_UTF8).getStr());
1065 sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList);
1066 pFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef);
1068 sal_Int32 diagramCount;
1069 diagramCount = nAnchorId;
1071 pFS->singleElementNS(XML_wp, XML_cNvGraphicFramePr,
1072 FSEND);
1074 pFS->startElementNS(XML_a, XML_graphic,
1075 FSNS(XML_xmlns, XML_a), "http://schemas.openxmlformats.org/drawingml/2006/main",
1076 FSEND);
1078 pFS->startElementNS(XML_a, XML_graphicData,
1079 XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/diagram",
1080 FSEND);
1082 // add data relation
1083 OUString dataFileName = "diagrams/data" + OUString::number(diagramCount) + ".xml";
1084 OString dataRelId = OUStringToOString(m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(),
1085 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramData",
1086 dataFileName, false), RTL_TEXTENCODING_UTF8);
1089 // add layout relation
1090 OUString layoutFileName = "diagrams/layout" + OUString::number(diagramCount) + ".xml";
1091 OString layoutRelId = OUStringToOString(m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(),
1092 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramLayout",
1093 layoutFileName, false), RTL_TEXTENCODING_UTF8);
1095 // add style relation
1096 OUString styleFileName = "diagrams/quickStyle" + OUString::number(diagramCount) + ".xml";
1097 OString styleRelId = OUStringToOString(m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(),
1098 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramQuickStyle",
1099 styleFileName , false), RTL_TEXTENCODING_UTF8);
1101 // add color relation
1102 OUString colorFileName = "diagrams/colors" + OUString::number(diagramCount) + ".xml";
1103 OString colorRelId = OUStringToOString(m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(),
1104 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramColors",
1105 colorFileName, false), RTL_TEXTENCODING_UTF8);
1107 OUString drawingFileName;
1108 if (drawingDom.is())
1110 // add drawing relation
1111 drawingFileName = "diagrams/drawing" + OUString::number(diagramCount) + ".xml";
1112 OUString drawingRelId = m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(),
1113 "http://schemas.microsoft.com/office/2007/relationships/diagramDrawing",
1114 drawingFileName , false);
1116 // the data dom contains a reference to the drawing relation. We need to update it with the new generated
1117 // relation value before writing the dom to a file
1119 // Get the dsp:damaModelExt node from the dom
1120 uno::Reference< xml::dom::XNodeList > nodeList =
1121 dataDom->getElementsByTagNameNS("http://schemas.microsoft.com/office/drawing/2008/diagram", "dataModelExt");
1123 // There must be one element only so get it
1124 uno::Reference< xml::dom::XNode > node = nodeList->item(0);
1126 // Get the list of attributes of the node
1127 uno::Reference< xml::dom::XNamedNodeMap > nodeMap = node->getAttributes();
1129 // Get the node with the relId attribute and set its new value
1130 uno::Reference< xml::dom::XNode > relIdNode = nodeMap->getNamedItem("relId");
1131 relIdNode->setNodeValue(drawingRelId);
1134 pFS->singleElementNS(XML_dgm, XML_relIds,
1135 FSNS(XML_xmlns, XML_dgm), "http://schemas.openxmlformats.org/drawingml/2006/diagram",
1136 FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
1137 FSNS(XML_r, XML_dm), dataRelId.getStr(),
1138 FSNS(XML_r, XML_lo), layoutRelId.getStr(),
1139 FSNS(XML_r, XML_qs), styleRelId.getStr(),
1140 FSNS(XML_r, XML_cs), colorRelId.getStr(),
1141 FSEND);
1143 pFS->endElementNS(XML_a, XML_graphicData);
1144 pFS->endElementNS(XML_a, XML_graphic);
1145 endDMLAnchorInline(&rFrmFmt);
1147 uno::Reference< xml::sax::XSAXSerializable > serializer;
1148 uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create(comphelper::getProcessComponentContext());
1150 // write data file
1151 serializer.set(dataDom, uno::UNO_QUERY);
1152 uno::Reference< io::XOutputStream > xDataOutputStream = m_pImpl->m_rExport.GetFilter().openFragmentStream(
1153 "word/" + dataFileName, "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml");
1154 writer->setOutputStream(xDataOutputStream);
1155 serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW),
1156 uno::Sequence< beans::StringPair >());
1158 // write the associated Images and rels for data file
1159 writeDiagramRels(dataDom, xDataRelSeq, xDataOutputStream, OUString("OOXDiagramDataRels"), nAnchorId);
1161 // write layout file
1162 serializer.set(layoutDom, uno::UNO_QUERY);
1163 writer->setOutputStream(m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + layoutFileName,
1164 "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml"));
1165 serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW),
1166 uno::Sequence< beans::StringPair >());
1168 // write style file
1169 serializer.set(styleDom, uno::UNO_QUERY);
1170 writer->setOutputStream(m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + styleFileName,
1171 "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml"));
1172 serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW),
1173 uno::Sequence< beans::StringPair >());
1175 // write color file
1176 serializer.set(colorDom, uno::UNO_QUERY);
1177 writer->setOutputStream(m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + colorFileName,
1178 "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml"));
1179 serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW),
1180 uno::Sequence< beans::StringPair >());
1182 // write drawing file
1184 if (drawingDom.is())
1186 serializer.set(drawingDom, uno::UNO_QUERY);
1187 uno::Reference< io::XOutputStream > xDrawingOutputStream = m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + drawingFileName,
1188 "application/vnd.openxmlformats-officedocument.drawingml.diagramDrawing+xml");
1189 writer->setOutputStream(xDrawingOutputStream);
1190 serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW),
1191 uno::Sequence< beans::StringPair >());
1193 // write the associated Images and rels for drawing file
1194 uno::Sequence< uno::Sequence< uno::Any > > xDrawingRelSeq;
1195 diagramDrawing[1] >>= xDrawingRelSeq;
1196 writeDiagramRels(drawingDom, xDrawingRelSeq, xDrawingOutputStream, OUString("OOXDiagramDrawingRels"), nAnchorId);
1200 void DocxSdrExport::writeOnlyTextOfFrame(sw::Frame* pParentFrame)
1202 const SwFrmFmt& rFrmFmt = pParentFrame->GetFrmFmt();
1203 const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx();
1204 sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer;
1206 sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0;
1207 sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1209 //Save data here and restore when out of scope
1210 ExportDataSaveRestore aDataGuard(m_pImpl->m_rExport, nStt, nEnd, pParentFrame);
1212 m_pImpl->m_pBodyPrAttrList = pFS->createAttrList();
1213 m_pImpl->m_bFrameBtLr = checkFrameBtlr(m_pImpl->m_rExport.pDoc->GetNodes()[nStt], 0);
1214 m_pImpl->m_bFlyFrameGraphic = true;
1215 m_pImpl->m_rExport.WriteText();
1216 m_pImpl->m_bFlyFrameGraphic = false;
1217 m_pImpl->m_bFrameBtLr = false;
1220 void DocxSdrExport::writeDMLTextFrame(sw::Frame* pParentFrame, int nAnchorId, bool bTextBoxOnly)
1222 sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer;
1223 const SwFrmFmt& rFrmFmt = pParentFrame->GetFrmFmt();
1224 const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx();
1226 sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0;
1227 sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1229 //Save data here and restore when out of scope
1230 ExportDataSaveRestore aDataGuard(m_pImpl->m_rExport, nStt, nEnd, pParentFrame);
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();
1236 uno::Reference< drawing::XShape > xShape;
1237 const SdrObject* pSdrObj = rFrmFmt.FindRealSdrObject();
1238 if (pSdrObj)
1239 xShape = uno::Reference< drawing::XShape >(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();
1245 m_pImpl->m_pBodyPrAttrList = pFS->createAttrList();
1247 drawing::TextVerticalAdjust eAdjust = drawing::TextVerticalAdjust_TOP;
1248 if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("TextVerticalAdjust"))
1249 xPropertySet->getPropertyValue("TextVerticalAdjust") >>= eAdjust;
1250 m_pImpl->m_pBodyPrAttrList->add(XML_anchor, oox::drawingml::GetTextVerticalAdjust(eAdjust));
1253 if (!bTextBoxOnly)
1255 startDMLAnchorInline(&rFrmFmt, aSize);
1257 sax_fastparser::FastAttributeList* pDocPrAttrList = pFS->createAttrList();
1258 pDocPrAttrList->add(XML_id, OString::number(nAnchorId).getStr());
1259 pDocPrAttrList->add(XML_name, OUStringToOString(rFrmFmt.GetName(), RTL_TEXTENCODING_UTF8).getStr());
1260 sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList);
1261 pFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef);
1263 pFS->startElementNS(XML_a, XML_graphic,
1264 FSNS(XML_xmlns, XML_a), "http://schemas.openxmlformats.org/drawingml/2006/main",
1265 FSEND);
1266 pFS->startElementNS(XML_a, XML_graphicData,
1267 XML_uri, "http://schemas.microsoft.com/office/word/2010/wordprocessingShape",
1268 FSEND);
1269 pFS->startElementNS(XML_wps, XML_wsp, FSEND);
1270 pFS->singleElementNS(XML_wps, XML_cNvSpPr,
1271 XML_txBox, "1",
1272 FSEND);
1274 uno::Any aRotation ;
1275 sal_Int32 nRotation = 0;
1276 if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag"))
1278 uno::Sequence< beans::PropertyValue > propList;
1279 xPropertySet->getPropertyValue("FrameInteropGrabBag") >>= propList;
1280 for (sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp)
1282 OUString propName = propList[nProp].Name;
1283 if (propName == "mso-rotation-angle")
1285 aRotation = propList[nProp].Value ;
1286 break;
1290 aRotation >>= nRotation ;
1291 OString sRotation(OString::number(nRotation));
1292 // Shape properties
1293 pFS->startElementNS(XML_wps, XML_spPr, FSEND);
1294 if (nRotation)
1296 pFS->startElementNS(XML_a, XML_xfrm,
1297 XML_rot, sRotation.getStr(),
1298 FSEND);
1300 else
1302 pFS->startElementNS(XML_a, XML_xfrm, FSEND);
1304 pFS->singleElementNS(XML_a, XML_off,
1305 XML_x, "0",
1306 XML_y, "0",
1307 FSEND);
1308 OString aWidth(OString::number(TwipsToEMU(aSize.Width())));
1309 OString aHeight(OString::number(TwipsToEMU(aSize.Height())));
1310 pFS->singleElementNS(XML_a, XML_ext,
1311 XML_cx, aWidth.getStr(),
1312 XML_cy, aHeight.getStr(),
1313 FSEND);
1314 pFS->endElementNS(XML_a, XML_xfrm);
1315 OUString shapeType = "rect";
1316 if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag"))
1318 uno::Sequence< beans::PropertyValue > propList;
1319 xPropertySet->getPropertyValue("FrameInteropGrabBag") >>= propList;
1320 for (sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp)
1322 OUString propName = propList[nProp].Name;
1323 if (propName == "mso-orig-shape-type")
1325 propList[nProp].Value >>= shapeType;
1326 break;
1330 //Empty shapeType will lead to corruption so to avoid that shapeType is set to default i.e. "rect"
1331 if (shapeType.isEmpty())
1332 shapeType = "rect";
1334 pFS->singleElementNS(XML_a, XML_prstGeom,
1335 XML_prst, OUStringToOString(shapeType, RTL_TEXTENCODING_UTF8).getStr(),
1336 FSEND);
1337 m_pImpl->m_bDMLTextFrameSyntax = true;
1338 m_pImpl->m_rExport.OutputFormat(pParentFrame->GetFrmFmt(), false, false, true);
1339 m_pImpl->m_bDMLTextFrameSyntax = false;
1340 writeDMLEffectLst(rFrmFmt);
1341 pFS->endElementNS(XML_wps, XML_spPr);
1344 m_pImpl->m_rExport.mpParentFrame = NULL;
1345 bool skipTxBxContent = false ;
1346 bool isTxbxLinked = false ;
1348 /* Check if the text box is linked and then decides whether
1349 to write the tag txbx or linkedTxbx
1351 if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("ChainPrevName") &&
1352 xPropSetInfo->hasPropertyByName("ChainNextName"))
1354 OUString sChainPrevName;
1355 OUString sChainNextName;
1357 xPropertySet->getPropertyValue("ChainPrevName") >>= sChainPrevName ;
1358 xPropertySet->getPropertyValue("ChainNextName") >>= sChainNextName ;
1360 if (!sChainPrevName.isEmpty())
1362 /* no text content should be added to this tag,
1363 since the textbox is linked, the entire content
1364 is written in txbx block
1366 ++m_pImpl->m_nSeq ;
1367 pFS->singleElementNS(XML_wps, XML_linkedTxbx,
1368 XML_id, I32S(m_pImpl->m_nId),
1369 XML_seq, I32S(m_pImpl->m_nSeq),
1370 FSEND);
1371 skipTxBxContent = true ;
1373 //Text box chaining for a group of textboxes ends here,
1374 //therefore reset the seq.
1375 if (sChainNextName.isEmpty())
1376 m_pImpl->m_nSeq = 0 ;
1378 else if (sChainPrevName.isEmpty() && !sChainNextName.isEmpty())
1380 /* this is the first textbox in the chaining, we add the text content
1381 to this block*/
1382 ++m_pImpl->m_nId ;
1383 //since the text box is linked, it needs an id.
1384 pFS->startElementNS(XML_wps, XML_txbx,
1385 XML_id, I32S(m_pImpl->m_nId),
1386 FSEND);
1387 isTxbxLinked = true ;
1391 if (!skipTxBxContent)
1393 if (!isTxbxLinked)
1394 pFS->startElementNS(XML_wps, XML_txbx, FSEND);//text box is not linked, therefore no id.
1396 pFS->startElementNS(XML_w, XML_txbxContent, FSEND);
1398 m_pImpl->m_bFrameBtLr = checkFrameBtlr(m_pImpl->m_rExport.pDoc->GetNodes()[nStt], 0);
1399 m_pImpl->m_bFlyFrameGraphic = true;
1400 m_pImpl->m_rExport.WriteText();
1401 m_pImpl->m_bFlyFrameGraphic = false;
1402 m_pImpl->m_bFrameBtLr = false;
1404 pFS->endElementNS(XML_w, XML_txbxContent);
1405 pFS->endElementNS(XML_wps, XML_txbx);
1407 sax_fastparser::XFastAttributeListRef xBodyPrAttrList(m_pImpl->m_pBodyPrAttrList);
1408 m_pImpl->m_pBodyPrAttrList = NULL;
1409 if (!bTextBoxOnly)
1411 pFS->startElementNS(XML_wps, XML_bodyPr, xBodyPrAttrList);
1412 // AutoSize of the Text Frame.
1413 const SwFmtFrmSize& rSize = rFrmFmt.GetFrmSize();
1414 pFS->singleElementNS(XML_a, (rSize.GetHeightSizeType() == ATT_VAR_SIZE ? XML_spAutoFit : XML_noAutofit), FSEND);
1415 pFS->endElementNS(XML_wps, XML_bodyPr);
1417 pFS->endElementNS(XML_wps, XML_wsp);
1418 pFS->endElementNS(XML_a, XML_graphicData);
1419 pFS->endElementNS(XML_a, XML_graphic);
1421 // Relative size of the Text Frame.
1422 if (rSize.GetWidthPercent())
1424 pFS->startElementNS(XML_wp14, XML_sizeRelH,
1425 XML_relativeFrom, (rSize.GetWidthPercentRelation() == text::RelOrientation::PAGE_FRAME ? "page" : "margin"),
1426 FSEND);
1427 pFS->startElementNS(XML_wp14, XML_pctWidth, FSEND);
1428 pFS->writeEscaped(OUString::number(rSize.GetWidthPercent() * oox::drawingml::PER_PERCENT));
1429 pFS->endElementNS(XML_wp14, XML_pctWidth);
1430 pFS->endElementNS(XML_wp14, XML_sizeRelH);
1432 if (rSize.GetHeightPercent())
1434 pFS->startElementNS(XML_wp14, XML_sizeRelV,
1435 XML_relativeFrom, (rSize.GetHeightPercentRelation() == text::RelOrientation::PAGE_FRAME ? "page" : "margin"),
1436 FSEND);
1437 pFS->startElementNS(XML_wp14, XML_pctHeight, FSEND);
1438 pFS->writeEscaped(OUString::number(rSize.GetHeightPercent() * oox::drawingml::PER_PERCENT));
1439 pFS->endElementNS(XML_wp14, XML_pctHeight);
1440 pFS->endElementNS(XML_wp14, XML_sizeRelV);
1443 endDMLAnchorInline(&rFrmFmt);
1447 void DocxSdrExport::writeVMLTextFrame(sw::Frame* pParentFrame, bool bTextBoxOnly)
1449 sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer;
1450 const SwFrmFmt& rFrmFmt = pParentFrame->GetFrmFmt();
1451 const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx();
1453 sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0;
1454 sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1456 //Save data here and restore when out of scope
1457 ExportDataSaveRestore aDataGuard(m_pImpl->m_rExport, nStt, nEnd, pParentFrame);
1459 // When a frame has some low height, but automatically expanded due
1460 // to lots of contents, this size contains the real size.
1461 const Size aSize = pParentFrame->GetSize();
1462 m_pImpl->m_pFlyFrameSize = &aSize;
1464 m_pImpl->m_bTextFrameSyntax = true;
1465 m_pImpl->m_pFlyAttrList = pFS->createAttrList();
1466 m_pImpl->m_pTextboxAttrList = pFS->createAttrList();
1467 m_pImpl->m_aTextFrameStyle = "position:absolute";
1468 m_pImpl->m_rExport.OutputFormat(pParentFrame->GetFrmFmt(), false, false, true);
1469 m_pImpl->m_pFlyAttrList->add(XML_style, m_pImpl->m_aTextFrameStyle.makeStringAndClear());
1471 const SdrObject* pObject = pParentFrame->GetFrmFmt().FindRealSdrObject();
1472 if (pObject != NULL)
1474 OUString sAnchorId = lclGetAnchorIdFromGrabBag(pObject);
1475 if (!sAnchorId.isEmpty())
1476 m_pImpl->m_pFlyAttrList->addNS(XML_w14, XML_anchorId, OUStringToOString(sAnchorId, RTL_TEXTENCODING_UTF8));
1479 sax_fastparser::XFastAttributeListRef xFlyAttrList(m_pImpl->m_pFlyAttrList);
1480 m_pImpl->m_pFlyAttrList = NULL;
1481 m_pImpl->m_bFrameBtLr = checkFrameBtlr(m_pImpl->m_rExport.pDoc->GetNodes()[nStt], m_pImpl->m_pTextboxAttrList);
1482 sax_fastparser::XFastAttributeListRef xTextboxAttrList(m_pImpl->m_pTextboxAttrList);
1483 m_pImpl->m_pTextboxAttrList = NULL;
1484 m_pImpl->m_bTextFrameSyntax = false;
1485 m_pImpl->m_pFlyFrameSize = 0;
1486 m_pImpl->m_rExport.mpParentFrame = NULL;
1488 if (!bTextBoxOnly)
1490 pFS->startElementNS(XML_w, XML_pict, FSEND);
1491 pFS->startElementNS(XML_v, XML_rect, xFlyAttrList);
1492 m_pImpl->textFrameShadow(rFrmFmt);
1493 if (m_pImpl->m_pFlyFillAttrList)
1495 sax_fastparser::XFastAttributeListRef xFlyFillAttrList(m_pImpl->m_pFlyFillAttrList);
1496 m_pImpl->m_pFlyFillAttrList = NULL;
1497 pFS->singleElementNS(XML_v, XML_fill, xFlyFillAttrList);
1499 if (m_pImpl->m_pDashLineStyleAttr)
1501 sax_fastparser::XFastAttributeListRef xDashLineStyleAttr(m_pImpl->m_pDashLineStyleAttr);
1502 m_pImpl->m_pDashLineStyleAttr = NULL;
1503 pFS->singleElementNS(XML_v, XML_stroke, xDashLineStyleAttr);
1505 pFS->startElementNS(XML_v, XML_textbox, xTextboxAttrList);
1507 pFS->startElementNS(XML_w, XML_txbxContent, FSEND);
1508 m_pImpl->m_bFlyFrameGraphic = true;
1509 m_pImpl->m_rExport.WriteText();
1510 m_pImpl->m_bFlyFrameGraphic = false;
1511 pFS->endElementNS(XML_w, XML_txbxContent);
1512 if (!bTextBoxOnly)
1514 pFS->endElementNS(XML_v, XML_textbox);
1516 if (m_pImpl->m_pFlyWrapAttrList)
1518 sax_fastparser::XFastAttributeListRef xFlyWrapAttrList(m_pImpl->m_pFlyWrapAttrList);
1519 m_pImpl->m_pFlyWrapAttrList = NULL;
1520 pFS->singleElementNS(XML_w10, XML_wrap, xFlyWrapAttrList);
1523 pFS->endElementNS(XML_v, XML_rect);
1524 pFS->endElementNS(XML_w, XML_pict);
1526 m_pImpl->m_bFrameBtLr = false;
1529 bool DocxSdrExport::checkFrameBtlr(SwNode* pStartNode, sax_fastparser::FastAttributeList* pTextboxAttrList)
1531 // The intended usage is to pass either a valid VML or DML attribute list.
1532 assert(pTextboxAttrList || m_pImpl->m_pBodyPrAttrList);
1534 if (!pStartNode->IsTxtNode())
1535 return false;
1537 SwTxtNode* pTxtNode = static_cast<SwTxtNode*>(pStartNode);
1539 const SfxPoolItem* pItem = 0; // explicitly init to avoid warnings
1540 bool bItemSet = false;
1541 if (pTxtNode->HasSwAttrSet())
1543 const SwAttrSet& rAttrSet = pTxtNode->GetSwAttrSet();
1544 bItemSet = rAttrSet.GetItemState(RES_CHRATR_ROTATE, true, &pItem) == SFX_ITEM_SET;
1547 if (!bItemSet)
1549 if (!pTxtNode->HasHints())
1550 return false;
1552 SwTxtAttr* pTxtAttr = pTxtNode->GetTxtAttrAt(0, RES_TXTATR_AUTOFMT);
1554 if (!pTxtAttr || pTxtAttr->Which() != RES_TXTATR_AUTOFMT)
1555 return false;
1557 boost::shared_ptr<SfxItemSet> pItemSet = pTxtAttr->GetAutoFmt().GetStyleHandle();
1558 bItemSet = pItemSet->GetItemState(RES_CHRATR_ROTATE, true, &pItem) == SFX_ITEM_SET;
1561 if (bItemSet)
1563 const SvxCharRotateItem& rCharRotate = static_cast<const SvxCharRotateItem&>(*pItem);
1564 if (rCharRotate.GetValue() == 900)
1566 if (pTextboxAttrList)
1567 pTextboxAttrList->add(XML_style, "mso-layout-flow-alt:bottom-to-top");
1568 else
1569 m_pImpl->m_pBodyPrAttrList->add(XML_vert, "vert270");
1570 return true;
1573 return false;
1576 bool DocxSdrExport::isTextBox(const SwFrmFmt& rFrmFmt)
1578 return std::find(m_pImpl->m_aTextBoxes.begin(), m_pImpl->m_aTextBoxes.end(), &rFrmFmt) != m_pImpl->m_aTextBoxes.end();
1581 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */