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