Line data Source code
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/drawing/LineStyle.hpp>
12 : #include <com/sun/star/drawing/PointSequenceSequence.hpp>
13 : #include <com/sun/star/xml/sax/XSAXSerializable.hpp>
14 : #include <com/sun/star/xml/sax/Writer.hpp>
15 : #include <editeng/unoprnms.hxx>
16 : #include <editeng/charrotateitem.hxx>
17 : #include <svx/svdogrp.hxx>
18 : #include <oox/export/utils.hxx>
19 : #include <oox/token/properties.hxx>
20 : #include <textboxhelper.hxx>
21 : #include <fmtanchr.hxx>
22 : #include <fmtsrnd.hxx>
23 : #include <fmtcntnt.hxx>
24 : #include <ndtxt.hxx>
25 : #include <txatbase.hxx>
26 : #include <fmtfsize.hxx>
27 : #include <drawdoc.hxx>
28 : #include <docxattributeoutput.hxx>
29 : #include <docxexportfilter.hxx>
30 : #include <comphelper/seqstream.hxx>
31 : #include <comphelper/sequence.hxx>
32 :
33 : #include <IDocumentDrawModelAccess.hxx>
34 :
35 : using namespace com::sun::star;
36 : using namespace oox;
37 :
38 : namespace
39 : {
40 :
41 1303 : uno::Sequence<beans::PropertyValue> lclGetProperty(uno::Reference<drawing::XShape> rShape, const OUString& rPropName)
42 : {
43 1303 : uno::Sequence<beans::PropertyValue> aResult;
44 2606 : uno::Reference<beans::XPropertySet> xPropertySet(rShape, uno::UNO_QUERY);
45 2606 : uno::Reference<beans::XPropertySetInfo> xPropSetInfo;
46 :
47 1303 : if (!xPropertySet.is())
48 0 : return aResult;
49 :
50 1303 : xPropSetInfo = xPropertySet->getPropertySetInfo();
51 1303 : if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(rPropName))
52 : {
53 1220 : xPropertySet->getPropertyValue(rPropName) >>= aResult;
54 : }
55 1303 : return aResult;
56 : }
57 :
58 612 : OUString lclGetAnchorIdFromGrabBag(const SdrObject* pObj)
59 : {
60 612 : OUString aResult;
61 1224 : uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pObj)->getUnoShape(), uno::UNO_QUERY);
62 1224 : OUString aGrabBagName;
63 1224 : uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY);
64 612 : if (xServiceInfo->supportsService("com.sun.star.text.TextFrame"))
65 189 : aGrabBagName = "FrameInteropGrabBag";
66 : else
67 423 : aGrabBagName = "InteropGrabBag";
68 1224 : uno::Sequence< beans::PropertyValue > propList = lclGetProperty(xShape, aGrabBagName);
69 1004 : for (sal_Int32 nProp = 0; nProp < propList.getLength(); ++nProp)
70 : {
71 606 : OUString aPropName = propList[nProp].Name;
72 606 : if (aPropName == "AnchorId")
73 : {
74 214 : propList[nProp].Value >>= aResult;
75 214 : break;
76 : }
77 392 : }
78 1224 : return aResult;
79 : }
80 :
81 355 : void lclMovePositionWithRotation(awt::Point& aPos, const Size& rSize, sal_Int64 nRotation)
82 : {
83 : // code from ImplEESdrWriter::ImplFlipBoundingBox (filter/source/msfilter/eschesdo.cxx)
84 : // TODO: refactor
85 :
86 355 : if (nRotation == 0)
87 664 : return;
88 :
89 46 : if (nRotation < 0)
90 1 : nRotation = (36000 + nRotation) % 36000;
91 46 : if (nRotation % 18000 == 0)
92 26 : nRotation = 0;
93 109 : while (nRotation > 9000)
94 17 : nRotation = (18000 - (nRotation % 18000));
95 :
96 46 : double fVal = (double) nRotation * F_PI18000;
97 46 : double fCos = cos(fVal);
98 46 : double fSin = sin(fVal);
99 :
100 46 : double nWidthHalf = (double) rSize.Width() / 2;
101 46 : double nHeightHalf = (double) rSize.Height() / 2;
102 :
103 46 : double nXDiff = fSin * nHeightHalf + fCos * nWidthHalf - nWidthHalf;
104 46 : double nYDiff = fSin * nWidthHalf + fCos * nHeightHalf - nHeightHalf;
105 :
106 46 : aPos.X += nXDiff;
107 46 : aPos.Y += nYDiff;
108 : }
109 :
110 : }
111 :
112 326 : ExportDataSaveRestore::ExportDataSaveRestore(DocxExport& rExport, sal_uLong nStt, sal_uLong nEnd, sw::Frame* pParentFrame)
113 326 : : m_rExport(rExport)
114 : {
115 326 : m_rExport.SaveData(nStt, nEnd);
116 326 : m_rExport.m_pParentFrame = pParentFrame;
117 326 : }
118 :
119 326 : ExportDataSaveRestore::~ExportDataSaveRestore()
120 : {
121 326 : m_rExport.RestoreData();
122 326 : }
123 :
124 : /// Holds data used by DocxSdrExport only.
125 : struct DocxSdrExport::Impl
126 : {
127 : DocxSdrExport& m_rSdrExport;
128 : DocxExport& m_rExport;
129 : sax_fastparser::FSHelperPtr m_pSerializer;
130 : oox::drawingml::DrawingML* m_pDrawingML;
131 : const Size* m_pFlyFrameSize;
132 : bool m_bTextFrameSyntax;
133 : bool m_bDMLTextFrameSyntax;
134 : std::unique_ptr<sax_fastparser::FastAttributeList> m_pFlyAttrList;
135 : std::unique_ptr<sax_fastparser::FastAttributeList> m_pTextboxAttrList;
136 : OStringBuffer m_aTextFrameStyle;
137 : bool m_bFrameBtLr;
138 : bool m_bDrawingOpen;
139 : bool m_bParagraphSdtOpen;
140 : bool m_bParagraphHasDrawing; ///Flag for checking drawing in a paragraph.
141 : bool m_bFlyFrameGraphic;
142 : std::unique_ptr<sax_fastparser::FastAttributeList> m_pFlyFillAttrList;
143 : sax_fastparser::FastAttributeList* m_pFlyWrapAttrList;
144 : sax_fastparser::FastAttributeList* m_pBodyPrAttrList;
145 : std::unique_ptr<sax_fastparser::FastAttributeList> m_pDashLineStyleAttr;
146 : sal_Int32 m_nId ;
147 : sal_Int32 m_nSeq ;
148 : bool m_bDMLAndVMLDrawingOpen;
149 : /// List of TextBoxes in this document: they are exported as part of their shape, never alone.
150 : std::set<const SwFrameFormat*> m_aTextBoxes;
151 : /// Preserved rotation for TextFrames.
152 : sal_Int32 m_nDMLandVMLTextFrameRotation;
153 :
154 482 : Impl(DocxSdrExport& rSdrExport, DocxExport& rExport, sax_fastparser::FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML)
155 : : m_rSdrExport(rSdrExport),
156 : m_rExport(rExport),
157 : m_pSerializer(pSerializer),
158 : m_pDrawingML(pDrawingML),
159 : m_pFlyFrameSize(0),
160 : m_bTextFrameSyntax(false),
161 : m_bDMLTextFrameSyntax(false),
162 : m_bFrameBtLr(false),
163 : m_bDrawingOpen(false),
164 : m_bParagraphSdtOpen(false),
165 : m_bParagraphHasDrawing(false),
166 : m_bFlyFrameGraphic(false),
167 : m_pFlyWrapAttrList(0),
168 : m_pBodyPrAttrList(0),
169 : m_nId(0),
170 : m_nSeq(0),
171 : m_bDMLAndVMLDrawingOpen(false),
172 : m_aTextBoxes(SwTextBoxHelper::findTextBoxes(m_rExport.m_pDoc)),
173 482 : m_nDMLandVMLTextFrameRotation(0)
174 : {
175 482 : }
176 :
177 482 : ~Impl()
178 482 : {
179 482 : }
180 :
181 : /// Writes wp wrapper code around an SdrObject, which itself is written using drawingML syntax.
182 :
183 : void textFrameShadow(const SwFrameFormat& rFrameFormat);
184 : static bool isSupportedDMLShape(uno::Reference<drawing::XShape> xShape);
185 : /// Undo the text direction mangling done by the frame btLr handler in writerfilter::dmapper::DomainMapper::lcl_startCharacterGroup()
186 : bool checkFrameBtlr(SwNode* pStartNode, bool bDML);
187 : };
188 :
189 482 : DocxSdrExport::DocxSdrExport(DocxExport& rExport, sax_fastparser::FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML)
190 482 : : m_pImpl(o3tl::make_unique<Impl>(*this, rExport, pSerializer, pDrawingML))
191 : {
192 482 : }
193 :
194 482 : DocxSdrExport::~DocxSdrExport()
195 : {
196 482 : }
197 :
198 556 : void DocxSdrExport::setSerializer(sax_fastparser::FSHelperPtr pSerializer)
199 : {
200 556 : m_pImpl->m_pSerializer = pSerializer;
201 556 : }
202 :
203 282 : const Size* DocxSdrExport::getFlyFrameSize()
204 : {
205 282 : return m_pImpl->m_pFlyFrameSize;
206 : }
207 :
208 12346 : bool DocxSdrExport::getTextFrameSyntax()
209 : {
210 12346 : return m_pImpl->m_bTextFrameSyntax;
211 : }
212 :
213 12026 : bool DocxSdrExport::getDMLTextFrameSyntax()
214 : {
215 12026 : return m_pImpl->m_bDMLTextFrameSyntax;
216 : }
217 :
218 15489 : std::unique_ptr<sax_fastparser::FastAttributeList>& DocxSdrExport::getFlyAttrList()
219 : {
220 15489 : return m_pImpl->m_pFlyAttrList;
221 : }
222 :
223 122 : std::unique_ptr<sax_fastparser::FastAttributeList>& DocxSdrExport::getTextboxAttrList()
224 : {
225 122 : return m_pImpl->m_pTextboxAttrList;
226 : }
227 :
228 1516 : OStringBuffer& DocxSdrExport::getTextFrameStyle()
229 : {
230 1516 : return m_pImpl->m_aTextFrameStyle;
231 : }
232 :
233 12 : bool DocxSdrExport::getFrameBtLr()
234 : {
235 12 : return m_pImpl->m_bFrameBtLr;
236 : }
237 :
238 5 : bool DocxSdrExport::IsDrawingOpen()
239 : {
240 5 : return m_pImpl->m_bDrawingOpen;
241 : }
242 :
243 2 : void DocxSdrExport::setParagraphSdtOpen(bool bParagraphSdtOpen)
244 : {
245 2 : m_pImpl->m_bParagraphSdtOpen = bParagraphSdtOpen;
246 2 : }
247 :
248 14611 : bool DocxSdrExport::IsDMLAndVMLDrawingOpen()
249 : {
250 14611 : return m_pImpl->m_bDMLAndVMLDrawingOpen;
251 : }
252 :
253 85 : bool DocxSdrExport::IsParagraphHasDrawing()
254 : {
255 85 : return m_pImpl->m_bParagraphHasDrawing;
256 : }
257 :
258 7529 : void DocxSdrExport::setParagraphHasDrawing(bool bParagraphHasDrawing)
259 : {
260 7529 : m_pImpl->m_bParagraphHasDrawing = bParagraphHasDrawing;
261 7529 : }
262 :
263 21 : std::unique_ptr<sax_fastparser::FastAttributeList>& DocxSdrExport::getFlyFillAttrList()
264 : {
265 21 : return m_pImpl->m_pFlyFillAttrList;
266 : }
267 :
268 50 : sax_fastparser::FastAttributeList* DocxSdrExport::getFlyWrapAttrList()
269 : {
270 50 : return m_pImpl->m_pFlyWrapAttrList;
271 : }
272 :
273 272 : sax_fastparser::FastAttributeList* DocxSdrExport::getBodyPrAttrList()
274 : {
275 272 : return m_pImpl->m_pBodyPrAttrList;
276 : }
277 :
278 0 : std::unique_ptr<sax_fastparser::FastAttributeList>& DocxSdrExport::getDashLineStyle()
279 : {
280 0 : return m_pImpl->m_pDashLineStyleAttr;
281 : }
282 :
283 38 : void DocxSdrExport::setFlyWrapAttrList(sax_fastparser::FastAttributeList* pAttrList)
284 : {
285 38 : m_pImpl->m_pFlyWrapAttrList = pAttrList;
286 38 : }
287 :
288 503 : void DocxSdrExport::startDMLAnchorInline(const SwFrameFormat* pFrameFormat, const Size& rSize)
289 : {
290 503 : m_pImpl->m_bDrawingOpen = true;
291 503 : m_pImpl->m_bParagraphHasDrawing = true;
292 503 : m_pImpl->m_pSerializer->startElementNS(XML_w, XML_drawing, FSEND);
293 :
294 503 : const SvxLRSpaceItem pLRSpaceItem = pFrameFormat->GetLRSpace(false);
295 1006 : const SvxULSpaceItem pULSpaceItem = pFrameFormat->GetULSpace(false);
296 :
297 : bool isAnchor;
298 :
299 503 : if (m_pImpl->m_bFlyFrameGraphic)
300 : {
301 38 : isAnchor = false; // make Graphic object inside DMLTextFrame & VMLTextFrame as Inline
302 : }
303 : else
304 : {
305 465 : isAnchor = pFrameFormat->GetAnchor().GetAnchorId() != FLY_AS_CHAR;
306 : }
307 :
308 : // Count effectExtent values, their value is needed before dist{T,B,L,R} is written.
309 1006 : SvxShadowItem aShadowItem = pFrameFormat->GetShadow();
310 503 : sal_Int32 nLeftExt = 0, nRightExt = 0, nTopExt = 0, nBottomExt = 0;
311 503 : if (aShadowItem.GetLocation() != SVX_SHADOW_NONE)
312 : {
313 5 : sal_Int32 nShadowWidth(TwipsToEMU(aShadowItem.GetWidth()));
314 5 : switch (aShadowItem.GetLocation())
315 : {
316 : case SVX_SHADOW_TOPLEFT:
317 0 : nTopExt = nLeftExt = nShadowWidth;
318 0 : break;
319 : case SVX_SHADOW_TOPRIGHT:
320 0 : nTopExt = nRightExt = nShadowWidth;
321 0 : break;
322 : case SVX_SHADOW_BOTTOMLEFT:
323 0 : nBottomExt = nLeftExt = nShadowWidth;
324 0 : break;
325 : case SVX_SHADOW_BOTTOMRIGHT:
326 5 : nBottomExt = nRightExt = nShadowWidth;
327 5 : break;
328 : case SVX_SHADOW_NONE:
329 : case SVX_SHADOW_END:
330 0 : break;
331 : }
332 : }
333 498 : else if (const SdrObject* pObject = pFrameFormat->FindRealSdrObject())
334 : {
335 : // No shadow, but we have an idea what was the original effectExtent.
336 478 : uno::Any aAny;
337 478 : pObject->GetGrabBagItem(aAny);
338 956 : comphelper::SequenceAsHashMap aGrabBag(aAny);
339 478 : comphelper::SequenceAsHashMap::iterator it = aGrabBag.find("CT_EffectExtent");
340 478 : if (it != aGrabBag.end())
341 : {
342 243 : comphelper::SequenceAsHashMap aEffectExtent(it->second);
343 1215 : for (std::pair<const OUString, uno::Any>& rDirection : aEffectExtent)
344 : {
345 972 : if (rDirection.first == "l" && rDirection.second.has<sal_Int32>())
346 243 : nLeftExt = rDirection.second.get<sal_Int32>();
347 729 : else if (rDirection.first == "t" && rDirection.second.has<sal_Int32>())
348 243 : nTopExt = rDirection.second.get<sal_Int32>();
349 486 : else if (rDirection.first == "r" && rDirection.second.has<sal_Int32>())
350 243 : nRightExt = rDirection.second.get<sal_Int32>();
351 243 : else if (rDirection.first == "b" && rDirection.second.has<sal_Int32>())
352 243 : nBottomExt = rDirection.second.get<sal_Int32>();
353 243 : }
354 478 : }
355 : }
356 :
357 503 : if (isAnchor)
358 : {
359 364 : sax_fastparser::FastAttributeList* attrList = sax_fastparser::FastSerializerHelper::createAttrList();
360 364 : bool bOpaque = pFrameFormat->GetOpaque().GetValue();
361 364 : awt::Point aPos(pFrameFormat->GetHoriOrient().GetPos(), pFrameFormat->GetVertOrient().GetPos());
362 364 : const SdrObject* pObj = pFrameFormat->FindRealSdrObject();
363 364 : if (pObj != NULL)
364 : {
365 : // SdrObjects know their layer, consider that instead of the frame format.
366 355 : bOpaque = pObj->GetLayer() != pFrameFormat->GetDoc()->getIDocumentDrawModelAccess().GetHellId() && pObj->GetLayer() != pFrameFormat->GetDoc()->getIDocumentDrawModelAccess().GetInvisibleHellId();
367 :
368 355 : lclMovePositionWithRotation(aPos, rSize, pObj->GetRotateAngle());
369 : }
370 364 : attrList->add(XML_behindDoc, bOpaque ? "0" : "1");
371 364 : attrList->add(XML_distT, OString::number(TwipsToEMU(pULSpaceItem.GetUpper()) - nTopExt).getStr());
372 364 : attrList->add(XML_distB, OString::number(TwipsToEMU(pULSpaceItem.GetLower()) - nBottomExt).getStr());
373 364 : attrList->add(XML_distL, OString::number(TwipsToEMU(pLRSpaceItem.GetLeft()) - nLeftExt).getStr());
374 364 : attrList->add(XML_distR, OString::number(TwipsToEMU(pLRSpaceItem.GetRight()) - nRightExt).getStr());
375 364 : attrList->add(XML_simplePos, "0");
376 364 : attrList->add(XML_locked, "0");
377 364 : attrList->add(XML_layoutInCell, "1");
378 364 : attrList->add(XML_allowOverlap, "1"); // TODO
379 364 : if (pObj != NULL)
380 : // It seems 0 and 1 have special meaning: just start counting from 2 to avoid issues with that.
381 355 : attrList->add(XML_relativeHeight, OString::number(pObj->GetOrdNum() + 2));
382 : else
383 : // relativeHeight is mandatory attribute, if value is not present, we must write default value
384 9 : attrList->add(XML_relativeHeight, "0");
385 364 : if (pObj != NULL)
386 : {
387 355 : OUString sAnchorId = lclGetAnchorIdFromGrabBag(pObj);
388 355 : if (!sAnchorId.isEmpty())
389 186 : attrList->addNS(XML_wp14, XML_anchorId, OUStringToOString(sAnchorId, RTL_TEXTENCODING_UTF8));
390 : }
391 364 : sax_fastparser::XFastAttributeListRef xAttrList(attrList);
392 364 : m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_anchor, xAttrList);
393 364 : m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_simplePos, XML_x, "0", XML_y, "0", FSEND); // required, unused
394 : const char* relativeFromH;
395 : const char* relativeFromV;
396 364 : const char* alignH = NULL;
397 364 : const char* alignV = NULL;
398 364 : switch (pFrameFormat->GetVertOrient().GetRelationOrient())
399 : {
400 : case text::RelOrientation::PAGE_PRINT_AREA:
401 10 : relativeFromV = "margin";
402 10 : break;
403 : case text::RelOrientation::PAGE_FRAME:
404 47 : relativeFromV = "page";
405 47 : break;
406 : case text::RelOrientation::FRAME:
407 304 : relativeFromV = "paragraph";
408 304 : break;
409 : case text::RelOrientation::TEXT_LINE:
410 : default:
411 3 : relativeFromV = "line";
412 3 : break;
413 : }
414 364 : switch (pFrameFormat->GetVertOrient().GetVertOrient())
415 : {
416 : case text::VertOrientation::TOP:
417 : case text::VertOrientation::CHAR_TOP:
418 : case text::VertOrientation::LINE_TOP:
419 19 : if (pFrameFormat->GetVertOrient().GetRelationOrient() == text::RelOrientation::TEXT_LINE)
420 0 : alignV = "bottom";
421 : else
422 19 : alignV = "top";
423 19 : break;
424 : case text::VertOrientation::BOTTOM:
425 : case text::VertOrientation::CHAR_BOTTOM:
426 : case text::VertOrientation::LINE_BOTTOM:
427 1 : if (pFrameFormat->GetVertOrient().GetRelationOrient() == text::RelOrientation::TEXT_LINE)
428 0 : alignV = "top";
429 : else
430 1 : alignV = "bottom";
431 1 : break;
432 : case text::VertOrientation::CENTER:
433 : case text::VertOrientation::CHAR_CENTER:
434 : case text::VertOrientation::LINE_CENTER:
435 5 : alignV = "center";
436 5 : break;
437 : default:
438 339 : break;
439 : }
440 364 : switch (pFrameFormat->GetHoriOrient().GetRelationOrient())
441 : {
442 : case text::RelOrientation::PAGE_PRINT_AREA:
443 22 : relativeFromH = "margin";
444 22 : break;
445 : case text::RelOrientation::PAGE_FRAME:
446 42 : relativeFromH = "page";
447 42 : break;
448 : case text::RelOrientation::CHAR:
449 0 : relativeFromH = "character";
450 0 : break;
451 : case text::RelOrientation::PAGE_RIGHT:
452 2 : relativeFromH = "page";
453 2 : alignH = "right";
454 2 : break;
455 : case text::RelOrientation::FRAME:
456 : default:
457 298 : relativeFromH = "column";
458 298 : break;
459 : }
460 364 : switch (pFrameFormat->GetHoriOrient().GetHoriOrient())
461 : {
462 : case text::HoriOrientation::LEFT:
463 1 : alignH = "left";
464 1 : break;
465 : case text::HoriOrientation::RIGHT:
466 6 : alignH = "right";
467 6 : break;
468 : case text::HoriOrientation::CENTER:
469 30 : alignH = "center";
470 30 : break;
471 : case text::HoriOrientation::INSIDE:
472 0 : alignH = "inside";
473 0 : break;
474 : case text::HoriOrientation::OUTSIDE:
475 0 : alignH = "outside";
476 0 : break;
477 : default:
478 327 : break;
479 : }
480 364 : m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_positionH, XML_relativeFrom, relativeFromH, FSEND);
481 : /**
482 : * Sizes of integral types
483 : * climits header defines constants with the limits of integral types for the specific system and compiler implemetation used.
484 : * Use of this might cause platform dependent problem like posOffset exceed the limit.
485 : **/
486 364 : const sal_Int64 MAX_INTEGER_VALUE = SAL_MAX_INT32;
487 364 : const sal_Int64 MIN_INTEGER_VALUE = SAL_MIN_INT32;
488 364 : if (alignH != NULL)
489 : {
490 39 : m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_align, FSEND);
491 39 : m_pImpl->m_pSerializer->write(alignH);
492 39 : m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_align);
493 : }
494 : else
495 : {
496 325 : m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_posOffset, FSEND);
497 325 : sal_Int64 nTwipstoEMU = TwipsToEMU(aPos.X);
498 :
499 : /* Absolute Position Offset Value is of type Int. Hence it should not be greater than
500 : * Maximum value for Int OR Less than the Minimum value for Int.
501 : * - Maximum value for Int = 2147483647
502 : * - Minimum value for Int = -2147483648
503 : *
504 : * As per ECMA Specification : ECMA-376, Second Edition,
505 : * Part 1 - Fundamentals And Markup Language Reference[20.4.3.3 ST_PositionOffset (Absolute Position Offset Value)]
506 : *
507 : * Please refer : http://www.schemacentral.com/sc/xsd/t-xsd_int.html
508 : */
509 :
510 325 : if (nTwipstoEMU > MAX_INTEGER_VALUE)
511 : {
512 0 : nTwipstoEMU = MAX_INTEGER_VALUE;
513 : }
514 325 : else if (nTwipstoEMU < MIN_INTEGER_VALUE)
515 : {
516 0 : nTwipstoEMU = MIN_INTEGER_VALUE;
517 : }
518 325 : m_pImpl->m_pSerializer->write(nTwipstoEMU);
519 325 : m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_posOffset);
520 : }
521 364 : m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_positionH);
522 364 : m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_positionV, XML_relativeFrom, relativeFromV, FSEND);
523 364 : if (alignV != NULL)
524 : {
525 25 : m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_align, FSEND);
526 25 : m_pImpl->m_pSerializer->write(alignV);
527 25 : m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_align);
528 : }
529 : else
530 : {
531 339 : m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_posOffset, FSEND);
532 339 : sal_Int64 nTwipstoEMU = TwipsToEMU(aPos.Y);
533 339 : if (nTwipstoEMU > MAX_INTEGER_VALUE)
534 : {
535 0 : nTwipstoEMU = MAX_INTEGER_VALUE;
536 : }
537 339 : else if (nTwipstoEMU < MIN_INTEGER_VALUE)
538 : {
539 0 : nTwipstoEMU = MIN_INTEGER_VALUE;
540 : }
541 339 : m_pImpl->m_pSerializer->write(nTwipstoEMU);
542 339 : m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_posOffset);
543 : }
544 364 : m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_positionV);
545 : }
546 : else
547 : {
548 139 : sax_fastparser::FastAttributeList* aAttrList = sax_fastparser::FastSerializerHelper::createAttrList();
549 139 : aAttrList->add(XML_distT, OString::number(TwipsToEMU(pULSpaceItem.GetUpper())).getStr());
550 139 : aAttrList->add(XML_distB, OString::number(TwipsToEMU(pULSpaceItem.GetLower())).getStr());
551 139 : aAttrList->add(XML_distL, OString::number(TwipsToEMU(pLRSpaceItem.GetLeft())).getStr());
552 139 : aAttrList->add(XML_distR, OString::number(TwipsToEMU(pLRSpaceItem.GetRight())).getStr());
553 139 : const SdrObject* pObj = pFrameFormat->FindRealSdrObject();
554 139 : if (pObj != NULL)
555 : {
556 128 : OUString sAnchorId = lclGetAnchorIdFromGrabBag(pObj);
557 128 : if (!sAnchorId.isEmpty())
558 28 : aAttrList->addNS(XML_wp14, XML_anchorId, OUStringToOString(sAnchorId, RTL_TEXTENCODING_UTF8));
559 : }
560 139 : m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_inline, aAttrList);
561 : }
562 :
563 : // now the common parts
564 : // extent of the image
565 : /**
566 : * Extent width is of type long ( i.e cx & cy ) as
567 : *
568 : * per ECMA-376, Second Edition, Part 1 - Fundamentals And Markup Language Reference
569 : * [ 20.4.2.7 extent (Drawing Object Size)]
570 : *
571 : * cy is of type a:ST_PositiveCoordinate.
572 : * Minimum inclusive: 0
573 : * Maximum inclusive: 27273042316900
574 : *
575 : * reference : http://www.schemacentral.com/sc/ooxml/e-wp_extent-1.html
576 : *
577 : * Though ECMA mentions the max value as aforementioned. It appears that MSO does not
578 : * handle for the same, infact it acutally can handles a max value of int32 i.e
579 : * 2147483647( MAX_INTEGER_VALUE ).
580 : * Therefore changing the following accordingly so that LO sync's up with MSO.
581 : **/
582 503 : sal_uInt64 cx = 0 ;
583 503 : sal_uInt64 cy = 0 ;
584 503 : const sal_Int64 MAX_INTEGER_VALUE = SAL_MAX_INT32;
585 :
586 : // the 'Size' type uses 'long' for width and height, so on
587 : // platforms where 'long' is 32 bits they can obviously never be
588 : // larger than the max signed 32-bit integer.
589 : #if SAL_TYPES_SIZEOFLONG > 4
590 503 : if (rSize.Width() > MAX_INTEGER_VALUE)
591 0 : cx = MAX_INTEGER_VALUE ;
592 : else
593 : #endif
594 : {
595 503 : if (0 > rSize.Width())
596 0 : cx = 0 ;
597 : else
598 503 : cx = rSize.Width();
599 : }
600 :
601 : #if SAL_TYPES_SIZEOFLONG > 4
602 503 : if (rSize.Height() > MAX_INTEGER_VALUE)
603 0 : cy = MAX_INTEGER_VALUE ;
604 : else
605 : #endif
606 : {
607 503 : if (0 > rSize.Height())
608 0 : cy = 0 ;
609 : else
610 503 : cy = rSize.Height();
611 : }
612 :
613 503 : OString aWidth(OString::number(TwipsToEMU(cx)));
614 : //we explicitly check the converted EMU value for the range as mentioned in above comment.
615 503 : aWidth = (aWidth.toInt64() > 0 ? (aWidth.toInt64() > MAX_INTEGER_VALUE ? I64S(MAX_INTEGER_VALUE) : aWidth.getStr()): "0");
616 1006 : OString aHeight(OString::number(TwipsToEMU(cy)));
617 503 : aHeight = (aHeight.toInt64() > 0 ? (aHeight.toInt64() > MAX_INTEGER_VALUE ? I64S(MAX_INTEGER_VALUE) : aHeight.getStr()): "0");
618 :
619 503 : m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_extent,
620 : XML_cx, aWidth,
621 : XML_cy, aHeight,
622 503 : FSEND);
623 :
624 : // effectExtent, extent including the effect (shadow only for now)
625 503 : m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_effectExtent,
626 : XML_l, OString::number(nLeftExt),
627 : XML_t, OString::number(nTopExt),
628 : XML_r, OString::number(nRightExt),
629 : XML_b, OString::number(nBottomExt),
630 1006 : FSEND);
631 :
632 : // See if we know the exact wrap type from grab-bag.
633 503 : sal_Int32 nWrapToken = 0;
634 503 : if (const SdrObject* pObject = pFrameFormat->FindRealSdrObject())
635 : {
636 483 : uno::Any aAny;
637 483 : pObject->GetGrabBagItem(aAny);
638 966 : comphelper::SequenceAsHashMap aGrabBag(aAny);
639 483 : comphelper::SequenceAsHashMap::iterator it = aGrabBag.find("EG_WrapType");
640 483 : if (it != aGrabBag.end())
641 : {
642 7 : OUString sType = it->second.get<OUString>();
643 7 : if (sType == "wrapTight")
644 1 : nWrapToken = XML_wrapTight;
645 6 : else if (sType == "wrapThrough")
646 6 : nWrapToken = XML_wrapThrough;
647 : else
648 : SAL_WARN("sw.ww8", "DocxSdrExport::startDMLAnchorInline: unexpected EG_WrapType value");
649 :
650 7 : m_pImpl->m_pSerializer->startElementNS(XML_wp, nWrapToken,
651 7 : XML_wrapText, "bothSides", FSEND);
652 :
653 7 : it = aGrabBag.find("CT_WrapPath");
654 7 : if (it != aGrabBag.end())
655 : {
656 7 : m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_wrapPolygon,
657 : XML_edited, "0",
658 7 : FSEND);
659 7 : drawing::PointSequenceSequence aSeqSeq = it->second.get< drawing::PointSequenceSequence >();
660 14 : std::vector<awt::Point> aPoints(comphelper::sequenceToContainer<std::vector<awt::Point> >(aSeqSeq[0]));
661 91 : for (std::vector<awt::Point>::iterator i = aPoints.begin(); i != aPoints.end(); ++i)
662 : {
663 84 : awt::Point& rPoint = *i;
664 252 : m_pImpl->m_pSerializer->singleElementNS(XML_wp, (i == aPoints.begin() ? XML_start : XML_lineTo),
665 : XML_x, OString::number(rPoint.X),
666 : XML_y, OString::number(rPoint.Y),
667 336 : FSEND);
668 : }
669 14 : m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_wrapPolygon);
670 : }
671 :
672 7 : m_pImpl->m_pSerializer->endElementNS(XML_wp, nWrapToken);
673 483 : }
674 : }
675 :
676 : // Or if we have a contour.
677 503 : if (!nWrapToken && pFrameFormat->GetSurround().IsContour())
678 : {
679 3 : if (const SwNoTextNode* pNd = sw::util::GetNoTextNodeFromSwFrameFormat(*pFrameFormat))
680 : {
681 2 : const tools::PolyPolygon* pPolyPoly = pNd->HasContour();
682 2 : if (pPolyPoly && pPolyPoly->Count())
683 : {
684 2 : nWrapToken = XML_wrapTight;
685 2 : m_pImpl->m_pSerializer->startElementNS(XML_wp, nWrapToken,
686 2 : XML_wrapText, "bothSides", FSEND);
687 :
688 2 : m_pImpl->m_pSerializer->startElementNS(XML_wp, XML_wrapPolygon,
689 : XML_edited, "0",
690 2 : FSEND);
691 2 : Polygon aPoly = sw::util::CorrectWordWrapPolygonForExport(*pPolyPoly, pNd);
692 18 : for (sal_uInt16 i = 0; i < aPoly.GetSize(); ++i)
693 16 : m_pImpl->m_pSerializer->singleElementNS(XML_wp, (i == 0 ? XML_start : XML_lineTo),
694 16 : XML_x, OString::number(aPoly[i].X()),
695 16 : XML_y, OString::number(aPoly[i].Y()),
696 48 : FSEND);
697 2 : m_pImpl->m_pSerializer->endElementNS(XML_wp, XML_wrapPolygon);
698 :
699 2 : m_pImpl->m_pSerializer->endElementNS(XML_wp, nWrapToken);
700 : }
701 : }
702 : }
703 :
704 : // No? Then just approximate based on what we have.
705 503 : if (isAnchor && !nWrapToken)
706 : {
707 355 : switch (pFrameFormat->GetSurround().GetValue())
708 : {
709 : case SURROUND_NONE:
710 8 : m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_wrapTopAndBottom, FSEND);
711 8 : break;
712 : case SURROUND_THROUGHT:
713 280 : m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_wrapNone, FSEND);
714 280 : break;
715 : case SURROUND_PARALLEL:
716 46 : m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_wrapSquare,
717 46 : XML_wrapText, "bothSides", FSEND);
718 46 : break;
719 : case SURROUND_IDEAL:
720 : default:
721 21 : m_pImpl->m_pSerializer->singleElementNS(XML_wp, XML_wrapSquare,
722 21 : XML_wrapText, "largest", FSEND);
723 21 : break;
724 : }
725 1006 : }
726 503 : }
727 :
728 503 : void DocxSdrExport::endDMLAnchorInline(const SwFrameFormat* pFrameFormat)
729 : {
730 : bool isAnchor;
731 503 : if (m_pImpl->m_bFlyFrameGraphic)
732 : {
733 38 : isAnchor = false; // end Inline Graphic object inside DMLTextFrame
734 : }
735 : else
736 : {
737 465 : isAnchor = pFrameFormat->GetAnchor().GetAnchorId() != FLY_AS_CHAR;
738 : }
739 503 : m_pImpl->m_pSerializer->endElementNS(XML_wp, isAnchor ? XML_anchor : XML_inline);
740 :
741 503 : m_pImpl->m_pSerializer->endElementNS(XML_w, XML_drawing);
742 503 : m_pImpl->m_bDrawingOpen = false;
743 503 : }
744 :
745 355 : void DocxSdrExport::writeVMLDrawing(const SdrObject* sdrObj, const SwFrameFormat& rFrameFormat,const Point& rNdTopLeft)
746 : {
747 355 : bool bSwapInPage = false;
748 355 : if (!(sdrObj)->GetPage())
749 : {
750 0 : if (SdrModel* pModel = m_pImpl->m_rExport.m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
751 : {
752 0 : if (SdrPage* pPage = pModel->GetPage(0))
753 : {
754 0 : bSwapInPage = true;
755 0 : const_cast< SdrObject* >(sdrObj)->SetPage(pPage);
756 : }
757 : }
758 : }
759 :
760 355 : m_pImpl->m_pSerializer->startElementNS(XML_w, XML_pict, FSEND);
761 355 : m_pImpl->m_pDrawingML->SetFS(m_pImpl->m_pSerializer);
762 : // See WinwordAnchoring::SetAnchoring(), these are not part of the SdrObject, have to be passed around manually.
763 :
764 355 : SwFormatHoriOrient rHoriOri = (rFrameFormat).GetHoriOrient();
765 710 : SwFormatVertOrient rVertOri = (rFrameFormat).GetVertOrient();
766 355 : m_pImpl->m_rExport.VMLExporter().AddSdrObject(*(sdrObj),
767 710 : rHoriOri.GetHoriOrient(), rVertOri.GetVertOrient(),
768 355 : rHoriOri.GetRelationOrient(),
769 1775 : rVertOri.GetRelationOrient(), (&rNdTopLeft), true);
770 355 : m_pImpl->m_pSerializer->endElementNS(XML_w, XML_pict);
771 :
772 355 : if (bSwapInPage)
773 355 : const_cast< SdrObject* >(sdrObj)->SetPage(0);
774 355 : }
775 :
776 691 : bool lcl_isLockedCanvas(uno::Reference<drawing::XShape> xShape)
777 : {
778 691 : bool bRet = false;
779 : uno::Sequence< beans::PropertyValue > propList =
780 691 : lclGetProperty(xShape, "InteropGrabBag");
781 3369 : for (sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp)
782 : {
783 2686 : OUString propName = propList[nProp].Name;
784 2686 : if (propName == "LockedCanvas")
785 : {
786 : /*
787 : * Export as Locked Canvas only if the property
788 : * is in the PropertySet
789 : */
790 8 : bRet = true;
791 8 : break;
792 : }
793 2678 : }
794 691 : return bRet;
795 : }
796 :
797 336 : void DocxSdrExport::writeDMLDrawing(const SdrObject* pSdrObject, const SwFrameFormat* pFrameFormat, int nAnchorId)
798 : {
799 336 : uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pSdrObject)->getUnoShape(), uno::UNO_QUERY_THROW);
800 336 : if (!Impl::isSupportedDMLShape(xShape))
801 336 : return;
802 :
803 336 : m_pImpl->m_rExport.DocxAttrOutput().GetSdtEndBefore(pSdrObject);
804 :
805 672 : sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer;
806 336 : Size aSize(pSdrObject->GetLogicRect().GetWidth(), pSdrObject->GetLogicRect().GetHeight());
807 336 : startDMLAnchorInline(pFrameFormat, aSize);
808 :
809 336 : sax_fastparser::FastAttributeList* pDocPrAttrList = sax_fastparser::FastSerializerHelper::createAttrList();
810 336 : pDocPrAttrList->add(XML_id, OString::number(nAnchorId).getStr());
811 336 : pDocPrAttrList->add(XML_name, OUStringToOString(pSdrObject->GetName(), RTL_TEXTENCODING_UTF8).getStr());
812 336 : if (!pSdrObject->GetTitle().isEmpty())
813 3 : pDocPrAttrList->add(XML_title, OUStringToOString(pSdrObject->GetTitle(), RTL_TEXTENCODING_UTF8));
814 336 : if (!pSdrObject->GetDescription().isEmpty())
815 1 : pDocPrAttrList->add(XML_descr, OUStringToOString(pSdrObject->GetDescription(), RTL_TEXTENCODING_UTF8));
816 672 : sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList);
817 336 : pFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef);
818 :
819 672 : uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY_THROW);
820 336 : const char* pNamespace = "http://schemas.microsoft.com/office/word/2010/wordprocessingShape";
821 336 : if (xServiceInfo->supportsService("com.sun.star.drawing.GroupShape"))
822 29 : pNamespace = "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup";
823 307 : else if (xServiceInfo->supportsService("com.sun.star.drawing.GraphicObjectShape"))
824 34 : pNamespace = "http://schemas.openxmlformats.org/drawingml/2006/picture";
825 : pFS->startElementNS(XML_a, XML_graphic,
826 : FSNS(XML_xmlns, XML_a), "http://schemas.openxmlformats.org/drawingml/2006/main",
827 336 : FSEND);
828 : pFS->startElementNS(XML_a, XML_graphicData,
829 : XML_uri, pNamespace,
830 336 : FSEND);
831 :
832 336 : bool bLockedCanvas = lcl_isLockedCanvas(xShape);
833 336 : if (bLockedCanvas)
834 : pFS->startElementNS(XML_lc, XML_lockedCanvas,
835 : FSNS(XML_xmlns, XML_lc), "http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas",
836 4 : FSEND);
837 :
838 336 : m_pImpl->m_rExport.OutputDML(xShape);
839 :
840 336 : if (bLockedCanvas)
841 4 : pFS->endElementNS(XML_lc, XML_lockedCanvas);
842 336 : pFS->endElementNS(XML_a, XML_graphicData);
843 336 : pFS->endElementNS(XML_a, XML_graphic);
844 :
845 : // Relative size of the drawing.
846 336 : if (pSdrObject->GetRelativeWidth())
847 : {
848 : // At the moment drawinglayer objects are always relative from page.
849 : pFS->startElementNS(XML_wp14, XML_sizeRelH,
850 17 : XML_relativeFrom, (pSdrObject->GetRelativeWidthRelation() == text::RelOrientation::FRAME ? "margin" : "page"),
851 17 : FSEND);
852 17 : pFS->startElementNS(XML_wp14, XML_pctWidth, FSEND);
853 17 : pFS->writeEscaped(OUString::number(*pSdrObject->GetRelativeWidth() * 100 * oox::drawingml::PER_PERCENT));
854 17 : pFS->endElementNS(XML_wp14, XML_pctWidth);
855 17 : pFS->endElementNS(XML_wp14, XML_sizeRelH);
856 : }
857 336 : if (pSdrObject->GetRelativeHeight())
858 : {
859 : pFS->startElementNS(XML_wp14, XML_sizeRelV,
860 15 : XML_relativeFrom, (pSdrObject->GetRelativeHeightRelation() == text::RelOrientation::FRAME ? "margin" : "page"),
861 15 : FSEND);
862 15 : pFS->startElementNS(XML_wp14, XML_pctHeight, FSEND);
863 15 : pFS->writeEscaped(OUString::number(*pSdrObject->GetRelativeHeight() * 100 * oox::drawingml::PER_PERCENT));
864 15 : pFS->endElementNS(XML_wp14, XML_pctHeight);
865 15 : pFS->endElementNS(XML_wp14, XML_sizeRelV);
866 : }
867 :
868 672 : endDMLAnchorInline(pFrameFormat);
869 : }
870 :
871 68 : void DocxSdrExport::Impl::textFrameShadow(const SwFrameFormat& rFrameFormat)
872 : {
873 68 : SvxShadowItem aShadowItem = rFrameFormat.GetShadow();
874 68 : if (aShadowItem.GetLocation() == SVX_SHADOW_NONE)
875 63 : return;
876 :
877 10 : OString aShadowWidth(OString::number(double(aShadowItem.GetWidth()) / 20) + "pt");
878 10 : OString aOffset;
879 5 : switch (aShadowItem.GetLocation())
880 : {
881 : case SVX_SHADOW_TOPLEFT:
882 0 : aOffset = "-" + aShadowWidth + ",-" + aShadowWidth;
883 0 : break;
884 : case SVX_SHADOW_TOPRIGHT:
885 0 : aOffset = aShadowWidth + ",-" + aShadowWidth;
886 0 : break;
887 : case SVX_SHADOW_BOTTOMLEFT:
888 0 : aOffset = "-" + aShadowWidth + "," + aShadowWidth;
889 0 : break;
890 : case SVX_SHADOW_BOTTOMRIGHT:
891 5 : aOffset = aShadowWidth + "," + aShadowWidth;
892 5 : break;
893 : case SVX_SHADOW_NONE:
894 : case SVX_SHADOW_END:
895 0 : break;
896 : }
897 5 : if (aOffset.isEmpty())
898 0 : return;
899 :
900 5 : OString aShadowColor = msfilter::util::ConvertColor(aShadowItem.GetColor());
901 : m_pSerializer->singleElementNS(XML_v, XML_shadow,
902 : XML_on, "t",
903 10 : XML_color, "#" + aShadowColor,
904 : XML_offset, aOffset,
905 15 : FSEND);
906 : }
907 :
908 680 : bool DocxSdrExport::Impl::isSupportedDMLShape(uno::Reference<drawing::XShape> xShape)
909 : {
910 680 : bool supported = true;
911 :
912 680 : uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY_THROW);
913 680 : if (xServiceInfo->supportsService("com.sun.star.drawing.PolyPolygonShape") || xServiceInfo->supportsService("com.sun.star.drawing.PolyLineShape"))
914 3 : supported = false;
915 :
916 680 : return supported;
917 : }
918 :
919 355 : void DocxSdrExport::writeDMLAndVMLDrawing(const SdrObject* sdrObj, const SwFrameFormat& rFrameFormat,const Point& rNdTopLeft, int nAnchorId)
920 : {
921 355 : bool bDMLAndVMLDrawingOpen = m_pImpl->m_bDMLAndVMLDrawingOpen;
922 355 : m_pImpl->m_bDMLAndVMLDrawingOpen = true;
923 :
924 : // Depending on the shape type, we actually don't write the shape as DML.
925 355 : OUString sShapeType;
926 355 : sal_uInt32 nMirrorFlags = 0;
927 710 : uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(sdrObj)->getUnoShape(), uno::UNO_QUERY_THROW);
928 :
929 : // Locked canvas is OK inside DML.
930 355 : if (lcl_isLockedCanvas(xShape))
931 4 : bDMLAndVMLDrawingOpen = false;
932 :
933 355 : MSO_SPT eShapeType = EscherPropertyContainer::GetCustomShapeType(xShape, nMirrorFlags, sShapeType);
934 :
935 : // In case we are already inside a DML block, then write the shape only as VML, turn out that's allowed to do.
936 : // A common service created in util to check for VML shapes which are allowed to have textbox in content
937 355 : if ((msfilter::util::HasTextBoxContent(eShapeType)) && Impl::isSupportedDMLShape(xShape) && !bDMLAndVMLDrawingOpen)
938 : {
939 336 : m_pImpl->m_pSerializer->startElementNS(XML_mc, XML_AlternateContent, FSEND);
940 :
941 336 : const SdrObjGroup* pObjGroup = dynamic_cast<const SdrObjGroup*>(sdrObj);
942 336 : m_pImpl->m_pSerializer->startElementNS(XML_mc, XML_Choice,
943 : XML_Requires, (pObjGroup ? "wpg" : "wps"),
944 672 : FSEND);
945 336 : writeDMLDrawing(sdrObj, &rFrameFormat, nAnchorId);
946 336 : m_pImpl->m_pSerializer->endElementNS(XML_mc, XML_Choice);
947 :
948 336 : m_pImpl->m_pSerializer->startElementNS(XML_mc, XML_Fallback, FSEND);
949 336 : writeVMLDrawing(sdrObj, rFrameFormat, rNdTopLeft);
950 336 : m_pImpl->m_pSerializer->endElementNS(XML_mc, XML_Fallback);
951 :
952 336 : m_pImpl->m_pSerializer->endElementNS(XML_mc, XML_AlternateContent);
953 : }
954 : else
955 19 : writeVMLDrawing(sdrObj, rFrameFormat, rNdTopLeft);
956 :
957 710 : m_pImpl->m_bDMLAndVMLDrawingOpen = false;
958 355 : }
959 :
960 : // Converts ARGB transparency (0..255) to drawingml alpha (opposite, and 0..100000)
961 5 : OString lcl_ConvertTransparency(const Color& rColor)
962 : {
963 5 : if (rColor.GetTransparency() > 0)
964 : {
965 0 : sal_Int32 nTransparencyPercent = 100 - float(rColor.GetTransparency()) / 2.55;
966 0 : return OString::number(nTransparencyPercent * oox::drawingml::PER_PERCENT);
967 : }
968 : else
969 5 : return OString("");
970 : }
971 :
972 160 : void DocxSdrExport::writeDMLEffectLst(const SwFrameFormat& rFrameFormat)
973 : {
974 160 : SvxShadowItem aShadowItem = rFrameFormat.GetShadow();
975 :
976 : // Output effects
977 160 : if (aShadowItem.GetLocation() != SVX_SHADOW_NONE)
978 : {
979 : // Distance is measured diagonally from corner
980 5 : double nShadowDist = sqrt((double)aShadowItem.GetWidth()*aShadowItem.GetWidth()*2.0);
981 5 : OString aShadowDist(OString::number(TwipsToEMU(nShadowDist)));
982 10 : OString aShadowColor = msfilter::util::ConvertColor(aShadowItem.GetColor());
983 10 : OString aShadowAlpha = lcl_ConvertTransparency(aShadowItem.GetColor());
984 5 : sal_uInt32 nShadowDir = 0;
985 5 : switch (aShadowItem.GetLocation())
986 : {
987 : case SVX_SHADOW_TOPLEFT:
988 0 : nShadowDir = 13500000;
989 0 : break;
990 : case SVX_SHADOW_TOPRIGHT:
991 0 : nShadowDir = 18900000;
992 0 : break;
993 : case SVX_SHADOW_BOTTOMLEFT:
994 0 : nShadowDir = 8100000;
995 0 : break;
996 : case SVX_SHADOW_BOTTOMRIGHT:
997 5 : nShadowDir = 2700000;
998 5 : break;
999 : case SVX_SHADOW_NONE:
1000 : case SVX_SHADOW_END:
1001 0 : break;
1002 : }
1003 5 : OString aShadowDir(OString::number(nShadowDir));
1004 :
1005 5 : m_pImpl->m_pSerializer->startElementNS(XML_a, XML_effectLst, FSEND);
1006 5 : m_pImpl->m_pSerializer->startElementNS(XML_a, XML_outerShdw,
1007 : XML_dist, aShadowDist.getStr(),
1008 10 : XML_dir, aShadowDir.getStr(), FSEND);
1009 5 : if (aShadowAlpha.isEmpty())
1010 5 : m_pImpl->m_pSerializer->singleElementNS(XML_a, XML_srgbClr,
1011 10 : XML_val, aShadowColor.getStr(), FSEND);
1012 : else
1013 : {
1014 0 : m_pImpl->m_pSerializer->startElementNS(XML_a, XML_srgbClr, XML_val, aShadowColor.getStr(), FSEND);
1015 0 : m_pImpl->m_pSerializer->singleElementNS(XML_a, XML_alpha, XML_val, aShadowAlpha.getStr(), FSEND);
1016 0 : m_pImpl->m_pSerializer->endElementNS(XML_a, XML_srgbClr);
1017 : }
1018 5 : m_pImpl->m_pSerializer->endElementNS(XML_a, XML_outerShdw);
1019 10 : m_pImpl->m_pSerializer->endElementNS(XML_a, XML_effectLst);
1020 160 : }
1021 :
1022 160 : }
1023 :
1024 13 : void DocxSdrExport::writeDiagramRels(uno::Reference<xml::dom::XDocument> xDom,
1025 : const uno::Sequence< uno::Sequence< uno::Any > >& xRelSeq,
1026 : uno::Reference< io::XOutputStream > xOutStream, const OUString& sGrabBagProperyName,
1027 : int nAnchorId)
1028 : {
1029 : // add image relationships of OOXData, OOXDiagram
1030 13 : OUString sType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
1031 26 : uno::Reference< xml::sax::XSAXSerializable > xSerializer(xDom, uno::UNO_QUERY);
1032 26 : uno::Reference< xml::sax::XWriter > xWriter = xml::sax::Writer::create(comphelper::getProcessComponentContext());
1033 13 : xWriter->setOutputStream(xOutStream);
1034 :
1035 : // retrieve the relationships from Sequence
1036 39 : for (sal_Int32 j = 0; j < xRelSeq.getLength(); j++)
1037 : {
1038 : // diagramDataRelTuple[0] => RID,
1039 : // diagramDataRelTuple[1] => xInputStream
1040 : // diagramDataRelTuple[2] => extension
1041 26 : uno::Sequence< uno::Any > diagramDataRelTuple = xRelSeq[j];
1042 :
1043 52 : OUString sRelId, sExtension;
1044 26 : diagramDataRelTuple[0] >>= sRelId;
1045 26 : diagramDataRelTuple[2] >>= sExtension;
1046 52 : OUString sContentType;
1047 26 : if (sExtension.equalsIgnoreAsciiCase(".WMF"))
1048 4 : sContentType = "image/x-wmf";
1049 : else
1050 22 : sContentType = "image/" + sExtension.copy(1);
1051 26 : sRelId = sRelId.copy(3);
1052 :
1053 52 : StreamDataSequence dataSeq;
1054 26 : diagramDataRelTuple[1] >>= dataSeq;
1055 52 : uno::Reference<io::XInputStream> dataImagebin(new ::comphelper::SequenceInputStream(dataSeq));
1056 :
1057 52 : OUString sFragment("../media/");
1058 : //nAnchorId is used to make the name unique irrespective of the number of smart arts.
1059 26 : sFragment += sGrabBagProperyName + OUString::number(nAnchorId) + "_" + OUString::number(j) + sExtension;
1060 :
1061 52 : PropertySet aProps(xOutStream);
1062 26 : aProps.setAnyProperty(PROP_RelId, uno::makeAny(sal_Int32(sRelId.toInt32())));
1063 :
1064 26 : m_pImpl->m_rExport.GetFilter().addRelation(xOutStream, sType, sFragment);
1065 :
1066 26 : sFragment = sFragment.replaceFirst("..","word");
1067 52 : uno::Reference< io::XOutputStream > xBinOutStream = m_pImpl->m_rExport.GetFilter().openFragmentStream(sFragment, sContentType);
1068 :
1069 : try
1070 : {
1071 26 : sal_Int32 nBufferSize = 512;
1072 26 : uno::Sequence< sal_Int8 > aDataBuffer(nBufferSize);
1073 : sal_Int32 nRead;
1074 2516 : do
1075 : {
1076 2516 : nRead = dataImagebin->readBytes(aDataBuffer, nBufferSize);
1077 2516 : if (nRead)
1078 : {
1079 2490 : if (nRead < nBufferSize)
1080 : {
1081 26 : nBufferSize = nRead;
1082 26 : aDataBuffer.realloc(nRead);
1083 : }
1084 2490 : xBinOutStream->writeBytes(aDataBuffer);
1085 : }
1086 : }
1087 : while (nRead);
1088 26 : xBinOutStream->flush();
1089 : }
1090 0 : catch (const uno::Exception& rException)
1091 : {
1092 : SAL_WARN("sw.ww8", "DocxSdrExport::writeDiagramRels Failed to copy grabbaged Image: " << rException.Message);
1093 : }
1094 26 : dataImagebin->closeInput();
1095 39 : }
1096 13 : }
1097 :
1098 7 : void DocxSdrExport::writeDiagram(const SdrObject* sdrObject, const SwFrameFormat& rFrameFormat, int nAnchorId)
1099 : {
1100 7 : sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer;
1101 14 : uno::Reference< drawing::XShape > xShape(const_cast<SdrObject*>(sdrObject)->getUnoShape(), uno::UNO_QUERY);
1102 14 : uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
1103 :
1104 14 : uno::Reference<xml::dom::XDocument> dataDom;
1105 14 : uno::Reference<xml::dom::XDocument> layoutDom;
1106 14 : uno::Reference<xml::dom::XDocument> styleDom;
1107 14 : uno::Reference<xml::dom::XDocument> colorDom;
1108 14 : uno::Reference<xml::dom::XDocument> drawingDom;
1109 14 : uno::Sequence< uno::Sequence< uno::Any > > xDataRelSeq;
1110 14 : uno::Sequence< uno::Any > diagramDrawing;
1111 :
1112 : // retrieve the doms from the GrabBag
1113 14 : OUString pName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
1114 14 : uno::Sequence< beans::PropertyValue > propList;
1115 7 : xPropSet->getPropertyValue(pName) >>= propList;
1116 47 : for (sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp)
1117 : {
1118 40 : OUString propName = propList[nProp].Name;
1119 40 : if (propName == "OOXData")
1120 7 : propList[nProp].Value >>= dataDom;
1121 33 : else if (propName == "OOXLayout")
1122 7 : propList[nProp].Value >>= layoutDom;
1123 26 : else if (propName == "OOXStyle")
1124 7 : propList[nProp].Value >>= styleDom;
1125 19 : else if (propName == "OOXColor")
1126 7 : propList[nProp].Value >>= colorDom;
1127 12 : else if (propName == "OOXDrawing")
1128 : {
1129 6 : propList[nProp].Value >>= diagramDrawing;
1130 6 : diagramDrawing[0] >>= drawingDom; // if there is OOXDrawing property then set drawingDom here only.
1131 : }
1132 6 : else if (propName == "OOXDiagramDataRels")
1133 4 : propList[nProp].Value >>= xDataRelSeq;
1134 40 : }
1135 :
1136 : // check that we have the 4 mandatory XDocuments
1137 : // if not, there was an error importing and we won't output anything
1138 7 : if (!dataDom.is() || !layoutDom.is() || !styleDom.is() || !colorDom.is())
1139 7 : return;
1140 :
1141 : // write necessary tags to document.xml
1142 7 : Size aSize(sdrObject->GetSnapRect().GetWidth(), sdrObject->GetSnapRect().GetHeight());
1143 7 : startDMLAnchorInline(&rFrameFormat, aSize);
1144 :
1145 : // generate an unique id
1146 7 : sax_fastparser::FastAttributeList* pDocPrAttrList = sax_fastparser::FastSerializerHelper::createAttrList();
1147 7 : pDocPrAttrList->add(XML_id, OString::number(nAnchorId).getStr());
1148 14 : OUString sName = "Diagram" + OUString::number(nAnchorId);
1149 7 : pDocPrAttrList->add(XML_name, OUStringToOString(sName, RTL_TEXTENCODING_UTF8).getStr());
1150 14 : sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList);
1151 7 : pFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef);
1152 :
1153 : sal_Int32 diagramCount;
1154 7 : diagramCount = nAnchorId;
1155 :
1156 : pFS->singleElementNS(XML_wp, XML_cNvGraphicFramePr,
1157 7 : FSEND);
1158 :
1159 : pFS->startElementNS(XML_a, XML_graphic,
1160 : FSNS(XML_xmlns, XML_a), "http://schemas.openxmlformats.org/drawingml/2006/main",
1161 7 : FSEND);
1162 :
1163 : pFS->startElementNS(XML_a, XML_graphicData,
1164 : XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/diagram",
1165 7 : FSEND);
1166 :
1167 : // add data relation
1168 14 : OUString dataFileName = "diagrams/data" + OUString::number(diagramCount) + ".xml";
1169 7 : OString dataRelId = OUStringToOString(m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(),
1170 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramData",
1171 21 : dataFileName, false), RTL_TEXTENCODING_UTF8);
1172 :
1173 :
1174 : // add layout relation
1175 14 : OUString layoutFileName = "diagrams/layout" + OUString::number(diagramCount) + ".xml";
1176 7 : OString layoutRelId = OUStringToOString(m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(),
1177 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramLayout",
1178 21 : layoutFileName, false), RTL_TEXTENCODING_UTF8);
1179 :
1180 : // add style relation
1181 14 : OUString styleFileName = "diagrams/quickStyle" + OUString::number(diagramCount) + ".xml";
1182 7 : OString styleRelId = OUStringToOString(m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(),
1183 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramQuickStyle",
1184 21 : styleFileName , false), RTL_TEXTENCODING_UTF8);
1185 :
1186 : // add color relation
1187 14 : OUString colorFileName = "diagrams/colors" + OUString::number(diagramCount) + ".xml";
1188 7 : OString colorRelId = OUStringToOString(m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(),
1189 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramColors",
1190 21 : colorFileName, false), RTL_TEXTENCODING_UTF8);
1191 :
1192 14 : OUString drawingFileName;
1193 7 : if (drawingDom.is())
1194 : {
1195 : // add drawing relation
1196 6 : drawingFileName = "diagrams/drawing" + OUString::number(diagramCount) + ".xml";
1197 6 : OUString drawingRelId = m_pImpl->m_rExport.GetFilter().addRelation(pFS->getOutputStream(),
1198 : "http://schemas.microsoft.com/office/2007/relationships/diagramDrawing",
1199 12 : drawingFileName , false);
1200 :
1201 : // the data dom contains a reference to the drawing relation. We need to update it with the new generated
1202 : // relation value before writing the dom to a file
1203 :
1204 : // Get the dsp:damaModelExt node from the dom
1205 : uno::Reference< xml::dom::XNodeList > nodeList =
1206 12 : dataDom->getElementsByTagNameNS("http://schemas.microsoft.com/office/drawing/2008/diagram", "dataModelExt");
1207 :
1208 : // There must be one element only so get it
1209 12 : uno::Reference< xml::dom::XNode > node = nodeList->item(0);
1210 :
1211 : // Get the list of attributes of the node
1212 12 : uno::Reference< xml::dom::XNamedNodeMap > nodeMap = node->getAttributes();
1213 :
1214 : // Get the node with the relId attribute and set its new value
1215 12 : uno::Reference< xml::dom::XNode > relIdNode = nodeMap->getNamedItem("relId");
1216 12 : relIdNode->setNodeValue(drawingRelId);
1217 : }
1218 :
1219 : pFS->singleElementNS(XML_dgm, XML_relIds,
1220 : FSNS(XML_xmlns, XML_dgm), "http://schemas.openxmlformats.org/drawingml/2006/diagram",
1221 : FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
1222 : FSNS(XML_r, XML_dm), dataRelId.getStr(),
1223 : FSNS(XML_r, XML_lo), layoutRelId.getStr(),
1224 : FSNS(XML_r, XML_qs), styleRelId.getStr(),
1225 : FSNS(XML_r, XML_cs), colorRelId.getStr(),
1226 7 : FSEND);
1227 :
1228 7 : pFS->endElementNS(XML_a, XML_graphicData);
1229 7 : pFS->endElementNS(XML_a, XML_graphic);
1230 7 : endDMLAnchorInline(&rFrameFormat);
1231 :
1232 14 : uno::Reference< xml::sax::XSAXSerializable > serializer;
1233 14 : uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create(comphelper::getProcessComponentContext());
1234 :
1235 : // write data file
1236 7 : serializer.set(dataDom, uno::UNO_QUERY);
1237 7 : uno::Reference< io::XOutputStream > xDataOutputStream = m_pImpl->m_rExport.GetFilter().openFragmentStream(
1238 21 : "word/" + dataFileName, "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml");
1239 7 : writer->setOutputStream(xDataOutputStream);
1240 7 : serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW),
1241 7 : uno::Sequence< beans::StringPair >());
1242 :
1243 : // write the associated Images and rels for data file
1244 7 : writeDiagramRels(dataDom, xDataRelSeq, xDataOutputStream, OUString("OOXDiagramDataRels"), nAnchorId);
1245 :
1246 : // write layout file
1247 7 : serializer.set(layoutDom, uno::UNO_QUERY);
1248 28 : writer->setOutputStream(m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + layoutFileName,
1249 28 : "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml"));
1250 7 : serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW),
1251 7 : uno::Sequence< beans::StringPair >());
1252 :
1253 : // write style file
1254 7 : serializer.set(styleDom, uno::UNO_QUERY);
1255 28 : writer->setOutputStream(m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + styleFileName,
1256 28 : "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml"));
1257 7 : serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW),
1258 7 : uno::Sequence< beans::StringPair >());
1259 :
1260 : // write color file
1261 7 : serializer.set(colorDom, uno::UNO_QUERY);
1262 28 : writer->setOutputStream(m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + colorFileName,
1263 28 : "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml"));
1264 7 : serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW),
1265 7 : uno::Sequence< beans::StringPair >());
1266 :
1267 : // write drawing file
1268 :
1269 7 : if (drawingDom.is())
1270 : {
1271 6 : serializer.set(drawingDom, uno::UNO_QUERY);
1272 18 : uno::Reference< io::XOutputStream > xDrawingOutputStream = m_pImpl->m_rExport.GetFilter().openFragmentStream("word/" + drawingFileName,
1273 24 : "application/vnd.openxmlformats-officedocument.drawingml.diagramDrawing+xml");
1274 6 : writer->setOutputStream(xDrawingOutputStream);
1275 6 : serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW),
1276 6 : uno::Sequence< beans::StringPair >());
1277 :
1278 : // write the associated Images and rels for drawing file
1279 12 : uno::Sequence< uno::Sequence< uno::Any > > xDrawingRelSeq;
1280 6 : diagramDrawing[1] >>= xDrawingRelSeq;
1281 12 : writeDiagramRels(drawingDom, xDrawingRelSeq, xDrawingOutputStream, OUString("OOXDiagramDrawingRels"), nAnchorId);
1282 7 : }
1283 : }
1284 :
1285 1 : void DocxSdrExport::writeOnlyTextOfFrame(sw::Frame* pParentFrame)
1286 : {
1287 1 : const SwFrameFormat& rFrameFormat = pParentFrame->GetFrameFormat();
1288 1 : const SwNodeIndex* pNodeIndex = rFrameFormat.GetContent().GetContentIdx();
1289 1 : sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer;
1290 :
1291 1 : sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0;
1292 1 : sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1293 :
1294 : //Save data here and restore when out of scope
1295 2 : ExportDataSaveRestore aDataGuard(m_pImpl->m_rExport, nStt, nEnd, pParentFrame);
1296 :
1297 1 : m_pImpl->m_pBodyPrAttrList = sax_fastparser::FastSerializerHelper::createAttrList();
1298 1 : m_pImpl->m_bFrameBtLr = m_pImpl->checkFrameBtlr(m_pImpl->m_rExport.m_pDoc->GetNodes()[nStt], /*bDML=*/true);
1299 1 : m_pImpl->m_bFlyFrameGraphic = true;
1300 1 : m_pImpl->m_rExport.WriteText();
1301 1 : m_pImpl->m_bFlyFrameGraphic = false;
1302 2 : m_pImpl->m_bFrameBtLr = false;
1303 1 : }
1304 :
1305 21 : void DocxSdrExport::writeBoxItemLine(const SvxBoxItem& rBox)
1306 : {
1307 21 : const editeng::SvxBorderLine* pBorderLine = 0;
1308 :
1309 21 : if (rBox.GetTop())
1310 : {
1311 21 : pBorderLine = rBox.GetTop();
1312 : }
1313 0 : else if (rBox.GetLeft())
1314 : {
1315 0 : pBorderLine = rBox.GetLeft();
1316 : }
1317 0 : else if (rBox.GetBottom())
1318 : {
1319 0 : pBorderLine = rBox.GetBottom();
1320 : }
1321 0 : else if (rBox.GetRight())
1322 : {
1323 0 : pBorderLine = rBox.GetRight();
1324 : }
1325 :
1326 21 : if (!pBorderLine)
1327 : {
1328 21 : return;
1329 : }
1330 :
1331 21 : sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer;
1332 21 : double fConverted(editeng::ConvertBorderWidthToWord(pBorderLine->GetBorderLineStyle(), pBorderLine->GetWidth()));
1333 42 : OString sWidth(OString::number(TwipsToEMU(fConverted)));
1334 : pFS->startElementNS(XML_a, XML_ln,
1335 : XML_w, sWidth.getStr(),
1336 21 : FSEND);
1337 :
1338 21 : pFS->startElementNS(XML_a, XML_solidFill, FSEND);
1339 42 : OString sColor(msfilter::util::ConvertColor(pBorderLine->GetColor()));
1340 : pFS->singleElementNS(XML_a, XML_srgbClr,
1341 : XML_val, sColor,
1342 21 : FSEND);
1343 21 : pFS->endElementNS(XML_a, XML_solidFill);
1344 :
1345 21 : if (drawing::LineStyle_DASH == pBorderLine->GetBorderLineStyle()) // Line Style is Dash type
1346 0 : pFS->singleElementNS(XML_a, XML_prstDash, XML_val, "dash", FSEND);
1347 :
1348 42 : pFS->endElementNS(XML_a, XML_ln);
1349 : }
1350 :
1351 184 : void DocxSdrExport::writeDMLTextFrame(sw::Frame* pParentFrame, int nAnchorId, bool bTextBoxOnly)
1352 : {
1353 184 : bool bDMLAndVMLDrawingOpen = m_pImpl->m_bDMLAndVMLDrawingOpen;
1354 184 : m_pImpl->m_bDMLAndVMLDrawingOpen = true;
1355 :
1356 184 : sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer;
1357 184 : const SwFrameFormat& rFrameFormat = pParentFrame->GetFrameFormat();
1358 184 : const SwNodeIndex* pNodeIndex = rFrameFormat.GetContent().GetContentIdx();
1359 :
1360 184 : sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0;
1361 184 : sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1362 :
1363 : //Save data here and restore when out of scope
1364 368 : ExportDataSaveRestore aDataGuard(m_pImpl->m_rExport, nStt, nEnd, pParentFrame);
1365 :
1366 : // When a frame has some low height, but automatically expanded due
1367 : // to lots of contents, this size contains the real size.
1368 184 : const Size aSize = pParentFrame->GetSize();
1369 :
1370 368 : uno::Reference< drawing::XShape > xShape;
1371 184 : const SdrObject* pSdrObj = rFrameFormat.FindRealSdrObject();
1372 184 : if (pSdrObj)
1373 173 : xShape = uno::Reference< drawing::XShape >(const_cast<SdrObject*>(pSdrObj)->getUnoShape(), uno::UNO_QUERY);
1374 368 : uno::Reference< beans::XPropertySet > xPropertySet(xShape, uno::UNO_QUERY);
1375 368 : uno::Reference< beans::XPropertySetInfo > xPropSetInfo;
1376 184 : if (xPropertySet.is())
1377 173 : xPropSetInfo = xPropertySet->getPropertySetInfo();
1378 :
1379 184 : m_pImpl->m_pBodyPrAttrList = sax_fastparser::FastSerializerHelper::createAttrList();
1380 : {
1381 184 : drawing::TextVerticalAdjust eAdjust = drawing::TextVerticalAdjust_TOP;
1382 184 : if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("TextVerticalAdjust"))
1383 173 : xPropertySet->getPropertyValue("TextVerticalAdjust") >>= eAdjust;
1384 184 : m_pImpl->m_pBodyPrAttrList->add(XML_anchor, oox::drawingml::GetTextVerticalAdjust(eAdjust));
1385 : }
1386 :
1387 184 : if (!bTextBoxOnly)
1388 : {
1389 68 : startDMLAnchorInline(&rFrameFormat, aSize);
1390 :
1391 68 : sax_fastparser::FastAttributeList* pDocPrAttrList = sax_fastparser::FastSerializerHelper::createAttrList();
1392 68 : pDocPrAttrList->add(XML_id, OString::number(nAnchorId).getStr());
1393 68 : pDocPrAttrList->add(XML_name, OUStringToOString(rFrameFormat.GetName(), RTL_TEXTENCODING_UTF8).getStr());
1394 68 : sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList);
1395 68 : pFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef);
1396 :
1397 : pFS->startElementNS(XML_a, XML_graphic,
1398 : FSNS(XML_xmlns, XML_a), "http://schemas.openxmlformats.org/drawingml/2006/main",
1399 68 : FSEND);
1400 : pFS->startElementNS(XML_a, XML_graphicData,
1401 : XML_uri, "http://schemas.microsoft.com/office/word/2010/wordprocessingShape",
1402 68 : FSEND);
1403 68 : pFS->startElementNS(XML_wps, XML_wsp, FSEND);
1404 : pFS->singleElementNS(XML_wps, XML_cNvSpPr,
1405 : XML_txBox, "1",
1406 68 : FSEND);
1407 :
1408 136 : uno::Any aRotation ;
1409 68 : m_pImpl->m_nDMLandVMLTextFrameRotation = 0;
1410 68 : if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag"))
1411 : {
1412 60 : uno::Sequence< beans::PropertyValue > propList;
1413 60 : xPropertySet->getPropertyValue("FrameInteropGrabBag") >>= propList;
1414 95 : for (sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp)
1415 : {
1416 36 : OUString propName = propList[nProp].Name;
1417 36 : if (propName == "mso-rotation-angle")
1418 : {
1419 1 : aRotation = propList[nProp].Value ;
1420 1 : break;
1421 : }
1422 95 : }
1423 : }
1424 68 : aRotation >>= m_pImpl->m_nDMLandVMLTextFrameRotation ;
1425 136 : OString sRotation(OString::number((OOX_DRAWINGML_EXPORT_ROTATE_CLOCKWISIFY(m_pImpl->m_nDMLandVMLTextFrameRotation))));
1426 : // Shape properties
1427 68 : pFS->startElementNS(XML_wps, XML_spPr, FSEND);
1428 68 : if (m_pImpl->m_nDMLandVMLTextFrameRotation)
1429 : {
1430 : pFS->startElementNS(XML_a, XML_xfrm,
1431 : XML_rot, sRotation.getStr(),
1432 1 : FSEND);
1433 : }
1434 : else
1435 : {
1436 67 : pFS->startElementNS(XML_a, XML_xfrm, FSEND);
1437 : }
1438 : pFS->singleElementNS(XML_a, XML_off,
1439 : XML_x, "0",
1440 : XML_y, "0",
1441 68 : FSEND);
1442 136 : OString aWidth(OString::number(TwipsToEMU(aSize.Width())));
1443 136 : OString aHeight(OString::number(TwipsToEMU(aSize.Height())));
1444 : pFS->singleElementNS(XML_a, XML_ext,
1445 : XML_cx, aWidth.getStr(),
1446 : XML_cy, aHeight.getStr(),
1447 68 : FSEND);
1448 68 : pFS->endElementNS(XML_a, XML_xfrm);
1449 136 : OUString shapeType = "rect";
1450 68 : if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag"))
1451 : {
1452 60 : uno::Sequence< beans::PropertyValue > propList;
1453 60 : xPropertySet->getPropertyValue("FrameInteropGrabBag") >>= propList;
1454 96 : for (sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp)
1455 : {
1456 36 : OUString propName = propList[nProp].Name;
1457 36 : if (propName == "mso-orig-shape-type")
1458 : {
1459 0 : propList[nProp].Value >>= shapeType;
1460 0 : break;
1461 : }
1462 96 : }
1463 : }
1464 : //Empty shapeType will lead to corruption so to avoid that shapeType is set to default i.e. "rect"
1465 68 : if (shapeType.isEmpty())
1466 0 : shapeType = "rect";
1467 :
1468 : pFS->singleElementNS(XML_a, XML_prstGeom,
1469 : XML_prst, OUStringToOString(shapeType, RTL_TEXTENCODING_UTF8).getStr(),
1470 68 : FSEND);
1471 68 : m_pImpl->m_bDMLTextFrameSyntax = true;
1472 68 : m_pImpl->m_rExport.OutputFormat(pParentFrame->GetFrameFormat(), false, false, true);
1473 68 : m_pImpl->m_bDMLTextFrameSyntax = false;
1474 68 : writeDMLEffectLst(rFrameFormat);
1475 136 : pFS->endElementNS(XML_wps, XML_spPr);
1476 : }
1477 :
1478 184 : m_pImpl->m_rExport.m_pParentFrame = NULL;
1479 184 : bool skipTxBxContent = false ;
1480 184 : bool isTxbxLinked = false ;
1481 :
1482 : /* Check if the text box is linked and then decides whether
1483 : to write the tag txbx or linkedTxbx
1484 : */
1485 714 : if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("ChainPrevName") &&
1486 530 : xPropSetInfo->hasPropertyByName("ChainNextName"))
1487 : {
1488 173 : OUString sChainPrevName;
1489 346 : OUString sChainNextName;
1490 :
1491 173 : xPropertySet->getPropertyValue("ChainPrevName") >>= sChainPrevName ;
1492 173 : xPropertySet->getPropertyValue("ChainNextName") >>= sChainNextName ;
1493 :
1494 173 : if (!sChainPrevName.isEmpty())
1495 : {
1496 : /* no text content should be added to this tag,
1497 : since the textbox is linked, the entire content
1498 : is written in txbx block
1499 : */
1500 1 : ++m_pImpl->m_nSeq ;
1501 : pFS->singleElementNS(XML_wps, XML_linkedTxbx,
1502 1 : XML_id, I32S(m_pImpl->m_nId),
1503 1 : XML_seq, I32S(m_pImpl->m_nSeq),
1504 2 : FSEND);
1505 1 : skipTxBxContent = true ;
1506 :
1507 : //Text box chaining for a group of textboxes ends here,
1508 : //therefore reset the seq.
1509 1 : if (sChainNextName.isEmpty())
1510 1 : m_pImpl->m_nSeq = 0 ;
1511 : }
1512 172 : else if (sChainPrevName.isEmpty() && !sChainNextName.isEmpty())
1513 : {
1514 : /* this is the first textbox in the chaining, we add the text content
1515 : to this block*/
1516 1 : ++m_pImpl->m_nId ;
1517 : //since the text box is linked, it needs an id.
1518 : pFS->startElementNS(XML_wps, XML_txbx,
1519 1 : XML_id, I32S(m_pImpl->m_nId),
1520 1 : FSEND);
1521 1 : isTxbxLinked = true ;
1522 173 : }
1523 : }
1524 :
1525 184 : if (!skipTxBxContent)
1526 : {
1527 183 : if (!isTxbxLinked)
1528 182 : pFS->startElementNS(XML_wps, XML_txbx, FSEND);//text box is not linked, therefore no id.
1529 :
1530 183 : pFS->startElementNS(XML_w, XML_txbxContent, FSEND);
1531 :
1532 183 : m_pImpl->m_bFrameBtLr = m_pImpl->checkFrameBtlr(m_pImpl->m_rExport.m_pDoc->GetNodes()[nStt], /*bDML=*/true);
1533 183 : m_pImpl->m_bFlyFrameGraphic = true;
1534 183 : m_pImpl->m_rExport.WriteText();
1535 183 : if (m_pImpl->m_bParagraphSdtOpen)
1536 : {
1537 1 : m_pImpl->m_rExport.DocxAttrOutput().EndParaSdtBlock();
1538 1 : m_pImpl->m_bParagraphSdtOpen = false;
1539 : }
1540 183 : m_pImpl->m_bFlyFrameGraphic = false;
1541 183 : m_pImpl->m_bFrameBtLr = false;
1542 :
1543 183 : pFS->endElementNS(XML_w, XML_txbxContent);
1544 183 : pFS->endElementNS(XML_wps, XML_txbx);
1545 : }
1546 368 : sax_fastparser::XFastAttributeListRef xBodyPrAttrList(m_pImpl->m_pBodyPrAttrList);
1547 184 : m_pImpl->m_pBodyPrAttrList = NULL;
1548 184 : if (!bTextBoxOnly)
1549 : {
1550 68 : pFS->startElementNS(XML_wps, XML_bodyPr, xBodyPrAttrList);
1551 : // AutoSize of the Text Frame.
1552 68 : const SwFormatFrmSize& rSize = rFrameFormat.GetFrmSize();
1553 68 : pFS->singleElementNS(XML_a, (rSize.GetHeightSizeType() == ATT_VAR_SIZE ? XML_spAutoFit : XML_noAutofit), FSEND);
1554 68 : pFS->endElementNS(XML_wps, XML_bodyPr);
1555 :
1556 68 : pFS->endElementNS(XML_wps, XML_wsp);
1557 68 : pFS->endElementNS(XML_a, XML_graphicData);
1558 68 : pFS->endElementNS(XML_a, XML_graphic);
1559 :
1560 : // Relative size of the Text Frame.
1561 68 : if (rSize.GetWidthPercent())
1562 : {
1563 : pFS->startElementNS(XML_wp14, XML_sizeRelH,
1564 2 : XML_relativeFrom, (rSize.GetWidthPercentRelation() == text::RelOrientation::PAGE_FRAME ? "page" : "margin"),
1565 2 : FSEND);
1566 2 : pFS->startElementNS(XML_wp14, XML_pctWidth, FSEND);
1567 2 : pFS->writeEscaped(OUString::number(rSize.GetWidthPercent() * oox::drawingml::PER_PERCENT));
1568 2 : pFS->endElementNS(XML_wp14, XML_pctWidth);
1569 2 : pFS->endElementNS(XML_wp14, XML_sizeRelH);
1570 : }
1571 68 : if (rSize.GetHeightPercent())
1572 : {
1573 : pFS->startElementNS(XML_wp14, XML_sizeRelV,
1574 0 : XML_relativeFrom, (rSize.GetHeightPercentRelation() == text::RelOrientation::PAGE_FRAME ? "page" : "margin"),
1575 0 : FSEND);
1576 0 : pFS->startElementNS(XML_wp14, XML_pctHeight, FSEND);
1577 0 : pFS->writeEscaped(OUString::number(rSize.GetHeightPercent() * oox::drawingml::PER_PERCENT));
1578 0 : pFS->endElementNS(XML_wp14, XML_pctHeight);
1579 0 : pFS->endElementNS(XML_wp14, XML_sizeRelV);
1580 : }
1581 :
1582 68 : endDMLAnchorInline(&rFrameFormat);
1583 : }
1584 368 : m_pImpl->m_bDMLAndVMLDrawingOpen = bDMLAndVMLDrawingOpen;
1585 184 : }
1586 :
1587 141 : void DocxSdrExport::writeVMLTextFrame(sw::Frame* pParentFrame, bool bTextBoxOnly)
1588 : {
1589 141 : bool bDMLAndVMLDrawingOpen = m_pImpl->m_bDMLAndVMLDrawingOpen;
1590 141 : m_pImpl->m_bDMLAndVMLDrawingOpen = true;
1591 :
1592 141 : sax_fastparser::FSHelperPtr pFS = m_pImpl->m_pSerializer;
1593 141 : const SwFrameFormat& rFrameFormat = pParentFrame->GetFrameFormat();
1594 141 : const SwNodeIndex* pNodeIndex = rFrameFormat.GetContent().GetContentIdx();
1595 :
1596 141 : sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0;
1597 141 : sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
1598 :
1599 : //Save data here and restore when out of scope
1600 282 : ExportDataSaveRestore aDataGuard(m_pImpl->m_rExport, nStt, nEnd, pParentFrame);
1601 :
1602 : // When a frame has some low height, but automatically expanded due
1603 : // to lots of contents, this size contains the real size.
1604 141 : const Size aSize = pParentFrame->GetSize();
1605 141 : m_pImpl->m_pFlyFrameSize = &aSize;
1606 :
1607 141 : m_pImpl->m_bTextFrameSyntax = true;
1608 141 : m_pImpl->m_pFlyAttrList.reset(sax_fastparser::FastSerializerHelper::createAttrList());
1609 141 : m_pImpl->m_pTextboxAttrList.reset(sax_fastparser::FastSerializerHelper::createAttrList());
1610 141 : m_pImpl->m_aTextFrameStyle = "position:absolute";
1611 141 : if (!bTextBoxOnly)
1612 : {
1613 68 : OString sRotation(OString::number(m_pImpl->m_nDMLandVMLTextFrameRotation / -100));
1614 68 : m_pImpl->m_rExport.SdrExporter().getTextFrameStyle().append(";rotation:").append(sRotation);
1615 : }
1616 141 : m_pImpl->m_rExport.OutputFormat(pParentFrame->GetFrameFormat(), false, false, true);
1617 141 : m_pImpl->m_pFlyAttrList->add(XML_style, m_pImpl->m_aTextFrameStyle.makeStringAndClear());
1618 :
1619 141 : const SdrObject* pObject = pParentFrame->GetFrameFormat().FindRealSdrObject();
1620 141 : if (pObject != NULL)
1621 : {
1622 129 : OUString sAnchorId = lclGetAnchorIdFromGrabBag(pObject);
1623 129 : if (!sAnchorId.isEmpty())
1624 0 : m_pImpl->m_pFlyAttrList->addNS(XML_w14, XML_anchorId, OUStringToOString(sAnchorId, RTL_TEXTENCODING_UTF8));
1625 : }
1626 282 : sax_fastparser::XFastAttributeListRef xFlyAttrList(m_pImpl->m_pFlyAttrList.release());
1627 141 : m_pImpl->m_bFrameBtLr = m_pImpl->checkFrameBtlr(m_pImpl->m_rExport.m_pDoc->GetNodes()[nStt], /*bDML=*/false);
1628 282 : sax_fastparser::XFastAttributeListRef xTextboxAttrList(m_pImpl->m_pTextboxAttrList.release());
1629 141 : m_pImpl->m_bTextFrameSyntax = false;
1630 141 : m_pImpl->m_pFlyFrameSize = 0;
1631 141 : m_pImpl->m_rExport.m_pParentFrame = NULL;
1632 :
1633 141 : if (!bTextBoxOnly)
1634 : {
1635 68 : pFS->startElementNS(XML_w, XML_pict, FSEND);
1636 68 : pFS->startElementNS(XML_v, XML_rect, xFlyAttrList);
1637 68 : m_pImpl->textFrameShadow(rFrameFormat);
1638 68 : if (m_pImpl->m_pFlyFillAttrList)
1639 : {
1640 14 : sax_fastparser::XFastAttributeListRef xFlyFillAttrList(m_pImpl->m_pFlyFillAttrList.release());
1641 14 : pFS->singleElementNS(XML_v, XML_fill, xFlyFillAttrList);
1642 : }
1643 68 : if (m_pImpl->m_pDashLineStyleAttr)
1644 : {
1645 0 : sax_fastparser::XFastAttributeListRef xDashLineStyleAttr(m_pImpl->m_pDashLineStyleAttr.release());
1646 0 : pFS->singleElementNS(XML_v, XML_stroke, xDashLineStyleAttr);
1647 : }
1648 68 : pFS->startElementNS(XML_v, XML_textbox, xTextboxAttrList);
1649 : }
1650 141 : pFS->startElementNS(XML_w, XML_txbxContent, FSEND);
1651 141 : m_pImpl->m_bFlyFrameGraphic = true;
1652 141 : m_pImpl->m_rExport.WriteText();
1653 141 : if (m_pImpl->m_bParagraphSdtOpen)
1654 : {
1655 1 : m_pImpl->m_rExport.DocxAttrOutput().EndParaSdtBlock();
1656 1 : m_pImpl->m_bParagraphSdtOpen = false;
1657 : }
1658 141 : m_pImpl->m_bFlyFrameGraphic = false;
1659 141 : pFS->endElementNS(XML_w, XML_txbxContent);
1660 141 : if (!bTextBoxOnly)
1661 : {
1662 68 : pFS->endElementNS(XML_v, XML_textbox);
1663 :
1664 68 : if (m_pImpl->m_pFlyWrapAttrList)
1665 : {
1666 38 : sax_fastparser::XFastAttributeListRef xFlyWrapAttrList(m_pImpl->m_pFlyWrapAttrList);
1667 38 : m_pImpl->m_pFlyWrapAttrList = NULL;
1668 38 : pFS->singleElementNS(XML_w10, XML_wrap, xFlyWrapAttrList);
1669 : }
1670 :
1671 68 : pFS->endElementNS(XML_v, XML_rect);
1672 68 : pFS->endElementNS(XML_w, XML_pict);
1673 : }
1674 141 : m_pImpl->m_bFrameBtLr = false;
1675 :
1676 282 : m_pImpl->m_bDMLAndVMLDrawingOpen = bDMLAndVMLDrawingOpen;
1677 141 : }
1678 :
1679 325 : bool DocxSdrExport::Impl::checkFrameBtlr(SwNode* pStartNode, bool bDML)
1680 : {
1681 : // The intended usage is to pass either a valid VML or DML attribute list.
1682 : if (bDML)
1683 : assert(m_pBodyPrAttrList);
1684 : else
1685 : assert(m_pTextboxAttrList);
1686 :
1687 325 : if (!pStartNode->IsTextNode())
1688 31 : return false;
1689 :
1690 294 : SwTextNode* pTextNode = pStartNode->GetTextNode();
1691 :
1692 294 : const SfxPoolItem* pItem = 0; // explicitly init to avoid warnings
1693 294 : bool bItemSet = false;
1694 294 : if (pTextNode->HasSwAttrSet())
1695 : {
1696 216 : const SwAttrSet& rAttrSet = pTextNode->GetSwAttrSet();
1697 216 : bItemSet = rAttrSet.GetItemState(RES_CHRATR_ROTATE, true, &pItem) == SfxItemState::SET;
1698 : }
1699 :
1700 294 : if (!bItemSet)
1701 : {
1702 290 : if (!pTextNode->HasHints())
1703 255 : return false;
1704 :
1705 193 : SwTextAttr* pTextAttr = pTextNode->GetTextAttrAt(0, RES_TXTATR_AUTOFMT);
1706 :
1707 193 : if (!pTextAttr || pTextAttr->Which() != RES_TXTATR_AUTOFMT)
1708 61 : return false;
1709 :
1710 132 : std::shared_ptr<SfxItemSet> pItemSet = pTextAttr->GetAutoFormat().GetStyleHandle();
1711 132 : bItemSet = pItemSet->GetItemState(RES_CHRATR_ROTATE, true, &pItem) == SfxItemState::SET;
1712 : }
1713 :
1714 136 : if (bItemSet)
1715 : {
1716 6 : const SvxCharRotateItem& rCharRotate = static_cast<const SvxCharRotateItem&>(*pItem);
1717 6 : if (rCharRotate.GetValue() == 900)
1718 : {
1719 6 : if (bDML)
1720 3 : m_pBodyPrAttrList->add(XML_vert, "vert270");
1721 : else
1722 3 : m_pTextboxAttrList->add(XML_style, "mso-layout-flow-alt:bottom-to-top");
1723 6 : return true;
1724 : }
1725 : }
1726 130 : return false;
1727 : }
1728 :
1729 187 : bool DocxSdrExport::isTextBox(const SwFrameFormat& rFrameFormat)
1730 : {
1731 187 : return m_pImpl->m_aTextBoxes.find(&rFrameFormat) != m_pImpl->m_aTextBoxes.end();
1732 60 : }
1733 :
1734 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|