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/container/XNamed.hpp>
11 : #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
12 : #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
13 : #include <com/sun/star/drawing/LineStyle.hpp>
14 : #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
15 : #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
16 : #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
17 : #include <com/sun/star/drawing/FillStyle.hpp>
18 : #include <com/sun/star/table/BorderLine2.hpp>
19 : #include <com/sun/star/text/HoriOrientation.hpp>
20 : #include <com/sun/star/text/RelOrientation.hpp>
21 : #include <com/sun/star/text/SizeType.hpp>
22 : #include <com/sun/star/text/VertOrientation.hpp>
23 : #include <com/sun/star/text/WrapTextMode.hpp>
24 : #include <com/sun/star/text/WritingMode.hpp>
25 : #include <com/sun/star/text/TextContentAnchorType.hpp>
26 :
27 : #include <ooxml/resourceids.hxx>
28 : #include <filter/msfilter/escherex.hxx>
29 : #include <filter/msfilter/util.hxx>
30 : #include <svx/svdtrans.hxx>
31 :
32 : #include <dmapper/DomainMapper.hxx>
33 : #include "../dmapper/GraphicHelpers.hxx"
34 : #include <rtfsdrimport.hxx>
35 : #include <rtfreferenceproperties.hxx>
36 :
37 : #include <oox/vml/vmlformatting.hxx>
38 : #include <oox/helper/modelobjecthelper.hxx>
39 : #include <oox/drawingml/shapepropertymap.hxx>
40 : #include <oox/helper/propertyset.hxx>
41 :
42 : #define TWIP_TO_MM100(TWIP) ((TWIP) >= 0 ? (((TWIP)*127L+36L)/72L) : (((TWIP)*127L-36L)/72L))
43 :
44 : namespace writerfilter {
45 : namespace rtftok {
46 :
47 312 : RTFSdrImport::RTFSdrImport(RTFDocumentImpl& rDocument,
48 : uno::Reference<lang::XComponent> const& xDstDoc)
49 : : m_rImport(rDocument),
50 312 : m_bTextFrame(false)
51 : {
52 312 : uno::Reference<drawing::XDrawPageSupplier> xDrawings(xDstDoc, uno::UNO_QUERY);
53 312 : if (xDrawings.is())
54 296 : m_aParents.push(xDrawings->getDrawPage());
55 312 : }
56 :
57 936 : RTFSdrImport::~RTFSdrImport()
58 : {
59 312 : if (m_aParents.size())
60 296 : m_aParents.pop();
61 624 : }
62 :
63 102 : void RTFSdrImport::createShape(const OUString& aStr, uno::Reference<drawing::XShape>& xShape, uno::Reference<beans::XPropertySet>& xPropertySet)
64 : {
65 102 : if (m_rImport.getModelFactory().is())
66 100 : xShape.set(m_rImport.getModelFactory()->createInstance(aStr), uno::UNO_QUERY);
67 102 : xPropertySet.set(xShape, uno::UNO_QUERY);
68 102 : }
69 :
70 41 : std::vector<beans::PropertyValue> RTFSdrImport::getTextFrameDefaults(bool bNew)
71 : {
72 41 : std::vector<beans::PropertyValue> aRet;
73 82 : beans::PropertyValue aPropertyValue;
74 :
75 41 : aPropertyValue.Name = "HoriOrient";
76 41 : aPropertyValue.Value <<= text::HoriOrientation::NONE;
77 41 : aRet.push_back(aPropertyValue);
78 41 : aPropertyValue.Name = "HoriOrientRelation";
79 41 : aPropertyValue.Value <<= text::RelOrientation::FRAME;
80 41 : aRet.push_back(aPropertyValue);
81 41 : aPropertyValue.Name = "VertOrient";
82 41 : aPropertyValue.Value <<= text::VertOrientation::NONE;
83 41 : aRet.push_back(aPropertyValue);
84 41 : aPropertyValue.Name = "VertOrientRelation";
85 41 : aPropertyValue.Value <<= text::RelOrientation::FRAME;
86 41 : aRet.push_back(aPropertyValue);
87 41 : if (!bNew)
88 : {
89 11 : aPropertyValue.Name = "BackColorTransparency";
90 11 : aPropertyValue.Value <<= sal_Int32(100);
91 11 : aRet.push_back(aPropertyValue);
92 : }
93 : // See the spec, new-style frame default margins are specified in EMUs.
94 41 : aPropertyValue.Name = "LeftBorderDistance";
95 41 : aPropertyValue.Value <<= sal_Int32(bNew ? (91440 / 360) : 0);
96 41 : aRet.push_back(aPropertyValue);
97 41 : aPropertyValue.Name = "RightBorderDistance";
98 41 : aPropertyValue.Value <<= sal_Int32(bNew ? (91440 / 360) : 0);
99 41 : aRet.push_back(aPropertyValue);
100 41 : aPropertyValue.Name = "TopBorderDistance";
101 41 : aPropertyValue.Value <<= sal_Int32(bNew ? (45720 / 360) : 0);
102 41 : aRet.push_back(aPropertyValue);
103 41 : aPropertyValue.Name = "BottomBorderDistance";
104 41 : aPropertyValue.Value <<= sal_Int32(bNew ? (45720 / 360) : 0);
105 41 : aRet.push_back(aPropertyValue);
106 41 : aPropertyValue.Name = "SizeType";
107 41 : aPropertyValue.Value <<= text::SizeType::FIX;
108 41 : aRet.push_back(aPropertyValue);
109 82 : return aRet;
110 : }
111 :
112 3 : void RTFSdrImport::pushParent(uno::Reference<drawing::XShapes> xParent)
113 : {
114 3 : m_aParents.push(xParent);
115 3 : }
116 :
117 3 : void RTFSdrImport::popParent()
118 : {
119 3 : m_aParents.pop();
120 3 : }
121 :
122 68 : void RTFSdrImport::resolveDhgt(uno::Reference<beans::XPropertySet> xPropertySet, sal_Int32 nZOrder, bool bOldStyle)
123 : {
124 : writerfilter::dmapper::DomainMapper& rMapper =
125 68 : dynamic_cast<writerfilter::dmapper::DomainMapper&>(m_rImport.Mapper());
126 68 : writerfilter::dmapper::GraphicZOrderHelper* pHelper = rMapper.graphicZOrderHelper();
127 68 : xPropertySet->setPropertyValue("ZOrder", uno::makeAny(pHelper->findZOrder(nZOrder, bOldStyle)));
128 68 : pHelper->addItem(xPropertySet, nZOrder);
129 68 : }
130 :
131 32 : void RTFSdrImport::resolveFLine(uno::Reference<beans::XPropertySet> xPropertySet, sal_Int32 nFLine)
132 : {
133 32 : if (nFLine == 0)
134 19 : xPropertySet->setPropertyValue("LineStyle", uno::makeAny(drawing::LineStyle_NONE));
135 32 : }
136 :
137 38 : void RTFSdrImport::applyProperty(uno::Reference<drawing::XShape> xShape, const OUString& aKey, const OUString& aValue)
138 : {
139 38 : uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
140 38 : sal_Int16 nHoriOrient = 0;
141 38 : sal_Int16 nVertOrient = 0;
142 76 : boost::optional<bool> obFitShapeToText;
143 38 : bool bFilled = true;
144 :
145 38 : if (aKey == "posh")
146 : {
147 9 : switch (aValue.toInt32())
148 : {
149 : case 1:
150 0 : nHoriOrient = text::HoriOrientation::LEFT;
151 0 : break;
152 : case 2:
153 9 : nHoriOrient = text::HoriOrientation::CENTER;
154 9 : break;
155 : case 3:
156 0 : nHoriOrient = text::HoriOrientation::RIGHT;
157 0 : break;
158 : case 4:
159 0 : nHoriOrient = text::HoriOrientation::INSIDE;
160 0 : break;
161 : case 5:
162 0 : nHoriOrient = text::HoriOrientation::OUTSIDE;
163 0 : break;
164 : default:
165 0 : break;
166 : }
167 : }
168 29 : else if (aKey == "posv")
169 : {
170 3 : switch (aValue.toInt32())
171 : {
172 : case 1:
173 2 : nVertOrient = text::VertOrientation::TOP;
174 2 : break;
175 : case 2:
176 1 : nVertOrient = text::VertOrientation::CENTER;
177 1 : break;
178 : case 3:
179 0 : nVertOrient = text::VertOrientation::BOTTOM;
180 0 : break;
181 : default:
182 0 : break;
183 : }
184 : }
185 26 : else if (aKey == "fFitShapeToText")
186 5 : obFitShapeToText.reset(aValue.toInt32() == 1);
187 21 : else if (aKey == "fFilled")
188 19 : bFilled = aValue.toInt32() == 1;
189 2 : else if (aKey == "rotation")
190 : {
191 : // See DffPropertyReader::Fix16ToAngle(): in RTF, positive rotation angles are clockwise, we have them as counter-clockwise.
192 : // Additionally, RTF type is 0..360*2^16, our is 0..360*100.
193 2 : sal_Int32 nRotation = aValue.toInt32()*100/65536;
194 2 : xPropertySet->setPropertyValue("RotateAngle", uno::makeAny(sal_Int32(NormAngle360(nRotation * -1))));
195 : }
196 :
197 38 : if (nHoriOrient != 0)
198 9 : xPropertySet->setPropertyValue("HoriOrient", uno::makeAny(nHoriOrient));
199 38 : if (nVertOrient != 0)
200 3 : xPropertySet->setPropertyValue("VertOrient", uno::makeAny(nVertOrient));
201 38 : if (obFitShapeToText)
202 : {
203 5 : xPropertySet->setPropertyValue("SizeType", uno::makeAny(*obFitShapeToText ? text::SizeType::MIN : text::SizeType::FIX));
204 5 : xPropertySet->setPropertyValue("FrameIsAutomaticHeight", uno::makeAny(*obFitShapeToText));
205 : }
206 38 : if (!bFilled)
207 : {
208 12 : if (m_bTextFrame)
209 5 : xPropertySet->setPropertyValue("BackColorTransparency", uno::makeAny(sal_Int32(100)));
210 : else
211 7 : xPropertySet->setPropertyValue("FillStyle", uno::makeAny(drawing::FillStyle_NONE));
212 38 : }
213 38 : }
214 :
215 69 : void RTFSdrImport::resolve(RTFShape& rShape, bool bClose)
216 : {
217 69 : int nType = -1;
218 69 : bool bPib = false;
219 69 : bool bCustom = false;
220 69 : m_bTextFrame = false;
221 :
222 69 : uno::Reference<drawing::XShape> xShape;
223 130 : uno::Reference<beans::XPropertySet> xPropertySet;
224 : // Create this early, as custom shapes may have properties before the type arrives.
225 69 : createShape("com.sun.star.drawing.CustomShape", xShape, xPropertySet);
226 130 : uno::Any aAny;
227 130 : beans::PropertyValue aPropertyValue;
228 69 : awt::Rectangle aViewBox;
229 130 : std::vector<beans::PropertyValue> aPathPropVec;
230 : // Default line color is black in Word, blue in Writer.
231 130 : uno::Any aLineColor = uno::makeAny(COL_BLACK);
232 : // Default line width is 0.75 pt (26 mm100) in Word, 0 in Writer.
233 130 : uno::Any aLineWidth = uno::makeAny(sal_Int32(26));
234 69 : text::WritingMode eWritingMode = text::WritingMode_LR_TB;
235 : // Groupshape support
236 130 : boost::optional<sal_Int32> oGroupLeft, oGroupTop, oGroupRight, oGroupBottom;
237 130 : boost::optional<sal_Int32> oRelLeft, oRelTop, oRelRight, oRelBottom;
238 :
239 : // Importing these are not trivial, let the VML import do the hard work.
240 130 : oox::vml::FillModel aFillModel; // Gradient.
241 130 : oox::vml::ShadowModel aShadowModel; // Shadow.
242 :
243 69 : bool bOpaque = true;
244 :
245 130 : boost::optional<sal_Int16> oRelativeWidth, oRelativeHeight;
246 69 : sal_Int16 nRelativeWidthRelation = text::RelOrientation::PAGE_FRAME;
247 69 : sal_Int16 nRelativeHeightRelation = text::RelOrientation::PAGE_FRAME;
248 :
249 : // The spec doesn't state what is the default for shapeType, Word seems to implement it as a rectangle.
250 138 : if (std::find_if(rShape.aProperties.begin(),
251 : rShape.aProperties.end(),
252 138 : boost::bind(&OUString::equals, boost::bind(&std::pair<OUString, OUString>::first, _1), OUString("shapeType")))
253 276 : == rShape.aProperties.end())
254 4 : rShape.aProperties.insert(rShape.aProperties.begin(), std::pair<OUString, OUString>("shapeType", OUString::number(ESCHER_ShpInst_Rectangle)));
255 :
256 1998 : for (std::vector< std::pair<OUString, OUString> >::iterator i = rShape.aProperties.begin();
257 1332 : i != rShape.aProperties.end(); ++i)
258 : {
259 597 : if ( i->first == "shapeType" )
260 : {
261 69 : nType = i->second.toInt32();
262 69 : switch (nType)
263 : {
264 : case ESCHER_ShpInst_Line:
265 3 : createShape("com.sun.star.drawing.LineShape", xShape, xPropertySet);
266 3 : break;
267 : case ESCHER_ShpInst_Rectangle:
268 : case ESCHER_ShpInst_TextBox:
269 : // If we're inside a groupshape, can't use text frames.
270 50 : if (!bClose && m_aParents.size() == 1)
271 : {
272 30 : createShape("com.sun.star.text.TextFrame", xShape, xPropertySet);
273 30 : m_bTextFrame = true;
274 30 : std::vector<beans::PropertyValue> aDefaults = getTextFrameDefaults(true);
275 300 : for (size_t j = 0; j < aDefaults.size(); ++j)
276 300 : xPropertySet->setPropertyValue(aDefaults[j].Name, aDefaults[j].Value);
277 : }
278 : else
279 20 : bCustom = true;
280 50 : break;
281 : default:
282 16 : bCustom = true;
283 16 : break;
284 : }
285 :
286 : // Defaults
287 69 : aAny <<= (sal_uInt32)0xffffff; // White in Word, kind of blue in Writer.
288 69 : if (xPropertySet.is() && !m_bTextFrame)
289 37 : xPropertySet->setPropertyValue("FillColor", aAny);
290 : }
291 528 : else if ( i->first == "wzName" )
292 : {
293 2 : if (m_bTextFrame)
294 : {
295 0 : uno::Reference<container::XNamed> xNamed(xShape, uno::UNO_QUERY);
296 0 : xNamed->setName(i->second);
297 : }
298 : else
299 2 : xPropertySet->setPropertyValue("Name", uno::makeAny(i->second));
300 : }
301 526 : else if ( i->first == "wzDescription" )
302 8 : xPropertySet->setPropertyValue("Description", uno::makeAny(i->second));
303 518 : else if ( i->first == "pib" )
304 : {
305 5 : m_rImport.setDestinationText(i->second);
306 5 : bPib = true;
307 : }
308 513 : else if (i->first == "fillColor" && xPropertySet.is())
309 : {
310 21 : aAny <<= msfilter::util::BGRToRGB(i->second.toInt32());
311 21 : if (m_bTextFrame)
312 9 : xPropertySet->setPropertyValue("BackColor", aAny);
313 : else
314 12 : xPropertySet->setPropertyValue("FillColor", aAny);
315 :
316 : // fillType will decide, possible it'll be the start color of a gradient.
317 21 : aFillModel.moColor.set(OUString("#") + OStringToOUString(msfilter::util::ConvertColor(aAny.get<sal_Int32>()), RTL_TEXTENCODING_UTF8));
318 : }
319 492 : else if ( i->first == "fillBackColor" )
320 : // fillType will decide, possible it'll be the end color of a gradient.
321 8 : aFillModel.moColor2.set(OUString("#") + OStringToOUString(msfilter::util::ConvertColor(msfilter::util::BGRToRGB(i->second.toInt32())), RTL_TEXTENCODING_UTF8));
322 484 : else if (i->first == "lineColor")
323 21 : aLineColor <<= msfilter::util::BGRToRGB(i->second.toInt32());
324 463 : else if ( i->first == "lineBackColor" )
325 : ; // Ignore: complementer of lineColor
326 462 : else if (i->first == "txflTextFlow" && xPropertySet.is())
327 : {
328 2 : if (i->second.toInt32() == 1)
329 0 : eWritingMode = text::WritingMode_TB_RL;
330 : }
331 460 : else if (i->first == "fLine" && xPropertySet.is())
332 8 : resolveFLine(xPropertySet, i->second.toInt32());
333 452 : else if (i->first == "fillOpacity" && xPropertySet.is())
334 : {
335 0 : int opacity = 100 - (i->second.toInt32())*100/65536;
336 0 : aAny <<= uno::makeAny(sal_uInt32(opacity));
337 0 : xPropertySet->setPropertyValue("FillTransparence", aAny);
338 : }
339 452 : else if (i->first == "lineWidth")
340 23 : aLineWidth <<= i->second.toInt32()/360;
341 429 : else if ( i->first == "pVerticies" )
342 : {
343 3 : uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aCoordinates;
344 3 : sal_Int32 nSize = 0; // Size of a token (its value is hardwired in the exporter)
345 3 : sal_Int32 nCount = 0; // Number of tokens
346 3 : sal_Int32 nCharIndex = 0; // Character index
347 3 : sal_Int32 nIndex = 0; // Array index
348 122 : do
349 : {
350 122 : OUString aToken = i->second.getToken(0, ';', nCharIndex);
351 122 : if (!nSize)
352 3 : nSize = aToken.toInt32();
353 119 : else if (!nCount)
354 : {
355 3 : nCount = aToken.toInt32();
356 3 : aCoordinates.realloc(nCount);
357 : }
358 116 : else if (aToken.getLength())
359 : {
360 : // The coordinates are in an (x,y) form.
361 116 : aToken = aToken.copy(1, aToken.getLength() - 2);
362 116 : sal_Int32 nI = 0;
363 116 : boost::optional<sal_Int32> oX;
364 232 : boost::optional<sal_Int32> oY;
365 232 : do
366 : {
367 232 : OUString aPoint = aToken.getToken(0, ',', nI);
368 232 : if (!oX)
369 116 : oX.reset(aPoint.toInt32());
370 : else
371 116 : oY.reset(aPoint.toInt32());
372 : }
373 232 : while (nI >= 0);
374 116 : aCoordinates[nIndex].First.Value <<= *oX;
375 116 : aCoordinates[nIndex].Second.Value <<= *oY;
376 232 : nIndex++;
377 122 : }
378 : }
379 122 : while (nCharIndex >= 0);
380 3 : aPropertyValue.Name = "Coordinates";
381 3 : aPropertyValue.Value <<= aCoordinates;
382 3 : aPathPropVec.push_back(aPropertyValue);
383 : }
384 426 : else if ( i->first == "pSegmentInfo" )
385 : {
386 3 : uno::Sequence<drawing::EnhancedCustomShapeSegment> aSegments;
387 3 : sal_Int32 nSize = 0;
388 3 : sal_Int32 nCount = 0;
389 3 : sal_Int32 nCharIndex = 0;
390 3 : sal_Int32 nIndex = 0;
391 24 : do
392 : {
393 24 : sal_Int32 nSeg = i->second.getToken(0, ';', nCharIndex).toInt32();
394 24 : if (!nSize)
395 3 : nSize = nSeg;
396 21 : else if (!nCount)
397 : {
398 3 : nCount = nSeg;
399 3 : aSegments.realloc(nCount);
400 : }
401 : else
402 : {
403 18 : sal_Int32 nPoints = 1;
404 18 : if (nSeg >= 0x2000 && nSeg < 0x20FF)
405 : {
406 3 : nPoints = nSeg & 0x0FFF;
407 3 : nSeg &= 0xFF00;
408 : }
409 :
410 18 : switch (nSeg)
411 : {
412 : case 0x0001: // lineto
413 3 : aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::LINETO;
414 3 : aSegments[nIndex].Count = sal_Int32(1);
415 3 : break;
416 : case 0x4000: // moveto
417 5 : aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::MOVETO;
418 5 : aSegments[nIndex].Count = sal_Int32(1);
419 5 : break;
420 : case 0x2000: // curveto
421 3 : aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::CURVETO;
422 3 : aSegments[nIndex].Count = sal_Int32(nPoints);
423 3 : break;
424 : case 0xb300: // arcto
425 0 : aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::ARCTO;
426 0 : aSegments[nIndex].Count = sal_Int32(0);
427 0 : break;
428 : case 0xac00:
429 : case 0xaa00: // nofill
430 : case 0xab00: // nostroke
431 : case 0x6001: // close
432 1 : break;
433 : case 0x8000: // end
434 5 : aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
435 5 : aSegments[nIndex].Count = sal_Int32(0);
436 5 : break;
437 : default: // given number of lineto elements
438 1 : aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::LINETO;
439 1 : aSegments[nIndex].Count = nSeg;
440 1 : break;
441 : }
442 18 : nIndex++;
443 : }
444 : }
445 24 : while (nCharIndex >= 0);
446 3 : aPropertyValue.Name = "Segments";
447 3 : aPropertyValue.Value <<= aSegments;
448 3 : aPathPropVec.push_back(aPropertyValue);
449 : }
450 423 : else if ( i->first == "geoLeft" )
451 2 : aViewBox.X = i->second.toInt32();
452 421 : else if ( i->first == "geoTop" )
453 2 : aViewBox.Y = i->second.toInt32();
454 419 : else if ( i->first == "geoRight" )
455 3 : aViewBox.Width = i->second.toInt32();
456 416 : else if ( i->first == "geoBottom" )
457 3 : aViewBox.Height = i->second.toInt32();
458 413 : else if ( i->first == "dhgt" )
459 : {
460 : // dhgt is Word 2007, \shpz is Word 97-2003, the later has priority.
461 13 : if (!rShape.oZ)
462 0 : resolveDhgt(xPropertySet, i->second.toInt32(), /*bOldStyle=*/false);
463 : }
464 : // These are in EMU, convert to mm100.
465 400 : else if (i->first == "dxTextLeft")
466 12 : xPropertySet->setPropertyValue("LeftBorderDistance", uno::makeAny(i->second.toInt32() / 360));
467 388 : else if (i->first == "dyTextTop")
468 12 : xPropertySet->setPropertyValue("TopBorderDistance", uno::makeAny(i->second.toInt32() / 360));
469 376 : else if (i->first == "dxTextRight")
470 12 : xPropertySet->setPropertyValue("RightBorderDistance", uno::makeAny(i->second.toInt32() / 360));
471 364 : else if (i->first == "dyTextBottom")
472 12 : xPropertySet->setPropertyValue("BottomBorderDistance", uno::makeAny(i->second.toInt32() / 360));
473 352 : else if (i->first == "dxWrapDistLeft")
474 9 : xPropertySet->setPropertyValue("LeftMargin", uno::makeAny(i->second.toInt32() / 360));
475 343 : else if (i->first == "dyWrapDistTop")
476 9 : xPropertySet->setPropertyValue("TopMargin", uno::makeAny(i->second.toInt32() / 360));
477 334 : else if (i->first == "dxWrapDistRight")
478 9 : xPropertySet->setPropertyValue("RightMargin", uno::makeAny(i->second.toInt32() / 360));
479 325 : else if (i->first == "dyWrapDistBottom")
480 9 : xPropertySet->setPropertyValue("BottomMargin", uno::makeAny(i->second.toInt32() / 360));
481 316 : else if (i->first == "fillType")
482 : {
483 6 : switch (i->second.toInt32())
484 : {
485 : case 7: // Shade using the fillAngle
486 6 : aFillModel.moType.set(oox::XML_gradient);
487 6 : break;
488 : default:
489 : SAL_INFO("writerfilter", "TODO handle fillType value '" << i->second << "'");
490 0 : break;
491 : }
492 : }
493 310 : else if (i->first == "fillFocus")
494 6 : aFillModel.moFocus.set(i->second.toDouble() / 100); // percent
495 304 : else if (i->first == "fShadow" && xPropertySet.is())
496 : {
497 15 : if (i->second.toInt32() == 1)
498 12 : aShadowModel.mbHasShadow = true;
499 : }
500 289 : else if (i->first == "shadowColor")
501 12 : aShadowModel.moColor.set(OUString("#") + OStringToOUString(msfilter::util::ConvertColor(msfilter::util::BGRToRGB(i->second.toInt32())), RTL_TEXTENCODING_UTF8));
502 277 : else if (i->first == "shadowOffsetX")
503 : // EMUs to points
504 12 : aShadowModel.moOffset.set(OUString::number(i->second.toDouble() / 12700) + "pt");
505 265 : else if (i->first == "posh" || i->first == "posv" || i->first == "fFitShapeToText" || i->first == "fFilled" || i->first == "rotation")
506 27 : applyProperty(xShape, i->first, i->second);
507 238 : else if (i->first == "posrelh")
508 : {
509 14 : switch (i->second.toInt32())
510 : {
511 : case 1:
512 5 : rShape.nHoriOrientRelation = text::RelOrientation::PAGE_FRAME;
513 5 : break;
514 : default:
515 9 : break;
516 : }
517 : }
518 224 : else if (i->first == "posrelv")
519 : {
520 13 : switch (i->second.toInt32())
521 : {
522 : case 1:
523 5 : rShape.nVertOrientRelation = text::RelOrientation::PAGE_FRAME;
524 5 : break;
525 : default:
526 8 : break;
527 : }
528 : }
529 211 : else if (i->first == "groupLeft")
530 9 : oGroupLeft.reset(TWIP_TO_MM100(i->second.toInt32()));
531 202 : else if (i->first == "groupTop")
532 9 : oGroupTop.reset(TWIP_TO_MM100(i->second.toInt32()));
533 193 : else if (i->first == "groupRight")
534 9 : oGroupRight.reset(TWIP_TO_MM100(i->second.toInt32()));
535 184 : else if (i->first == "groupBottom")
536 9 : oGroupBottom.reset(TWIP_TO_MM100(i->second.toInt32()));
537 175 : else if (i->first == "relLeft")
538 9 : oRelLeft.reset(TWIP_TO_MM100(i->second.toInt32()));
539 166 : else if (i->first == "relTop")
540 9 : oRelTop.reset(TWIP_TO_MM100(i->second.toInt32()));
541 157 : else if (i->first == "relRight")
542 9 : oRelRight.reset(TWIP_TO_MM100(i->second.toInt32()));
543 148 : else if (i->first == "relBottom")
544 9 : oRelBottom.reset(TWIP_TO_MM100(i->second.toInt32()));
545 139 : else if (i->first == "fBehindDocument")
546 9 : bOpaque = !i->second.toInt32();
547 130 : else if (i->first == "pctHoriz" || i->first == "pctVert")
548 : {
549 6 : sal_Int16 nPercentage = rtl::math::round(i->second.toDouble() / 10);
550 6 : boost::optional<sal_Int16>& rPercentage = i->first == "pctHoriz" ? oRelativeWidth : oRelativeHeight;
551 6 : if (nPercentage)
552 6 : rPercentage = nPercentage;
553 : }
554 124 : else if (i->first == "sizerelh")
555 : {
556 1 : if (xPropertySet.is())
557 : {
558 1 : switch (i->second.toInt32())
559 : {
560 : case 0: // margin
561 0 : nRelativeWidthRelation = text::RelOrientation::FRAME;
562 0 : break;
563 : case 1: // page
564 1 : nRelativeWidthRelation = text::RelOrientation::PAGE_FRAME;
565 1 : break;
566 : default:
567 : SAL_WARN("writerfilter", "RTFSdrImport::resolve: unhandled sizerelh value: " << i->second);
568 0 : break;
569 : }
570 : }
571 : }
572 123 : else if (i->first == "sizerelv")
573 : {
574 3 : if (xPropertySet.is())
575 : {
576 3 : switch (i->second.toInt32())
577 : {
578 : case 0: // margin
579 3 : nRelativeHeightRelation = text::RelOrientation::FRAME;
580 3 : break;
581 : case 1: // page
582 0 : nRelativeHeightRelation = text::RelOrientation::PAGE_FRAME;
583 0 : break;
584 : default:
585 : SAL_WARN("writerfilter", "RTFSdrImport::resolve: unhandled sizerelv value: " << i->second);
586 0 : break;
587 : }
588 : }
589 : }
590 : else
591 : SAL_INFO("writerfilter", "TODO handle shape property '" << i->first << "':'" << i->second << "'");
592 : }
593 :
594 69 : if (xPropertySet.is())
595 : {
596 67 : if (!m_bTextFrame)
597 : {
598 37 : xPropertySet->setPropertyValue("LineColor", aLineColor);
599 37 : xPropertySet->setPropertyValue("LineWidth", aLineWidth);
600 : }
601 : else
602 : {
603 : static const OUString aBorders[] = {
604 : OUString("TopBorder"), OUString("LeftBorder"), OUString("BottomBorder"), OUString("RightBorder")
605 33 : };
606 150 : for (unsigned int i = 0; i < SAL_N_ELEMENTS(aBorders); ++i)
607 : {
608 120 : table::BorderLine2 aBorderLine = xPropertySet->getPropertyValue(aBorders[i]).get<table::BorderLine2>();
609 120 : aBorderLine.Color = aLineColor.get<sal_Int32>();
610 120 : aBorderLine.LineWidth = aLineWidth.get<sal_Int32>();
611 120 : xPropertySet->setPropertyValue(aBorders[i], uno::makeAny(aBorderLine));
612 : }
613 : }
614 67 : if (rShape.oZ)
615 44 : resolveDhgt(xPropertySet, *rShape.oZ, /*bOldStyle=*/false);
616 67 : if (m_bTextFrame)
617 : // Writer textframes implement text::WritingMode2, which is a different data type.
618 30 : xPropertySet->setPropertyValue("WritingMode", uno::makeAny(sal_Int16(eWritingMode)));
619 : else
620 37 : xPropertySet->setPropertyValue("TextWritingMode", uno::makeAny(eWritingMode));
621 : }
622 :
623 69 : if (nType == ESCHER_ShpInst_PictureFrame) // picture frame
624 : {
625 7 : if (bPib)
626 5 : m_rImport.resolvePict(false);
627 7 : return;
628 : }
629 :
630 62 : if (m_aParents.size() && m_aParents.top().is() && !m_bTextFrame)
631 31 : m_aParents.top()->add(xShape);
632 62 : if (bCustom && xShape.is())
633 : {
634 28 : uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY);
635 28 : xDefaulter->createCustomShapeDefaults(OUString::number(nType));
636 : }
637 :
638 : // Creating Path property
639 62 : uno::Sequence<beans::PropertyValue> aPathPropSeq(aPathPropVec.size());
640 62 : beans::PropertyValue* pPathValues = aPathPropSeq.getArray();
641 68 : for (std::vector<beans::PropertyValue>::iterator i = aPathPropVec.begin(); i != aPathPropVec.end(); ++i)
642 6 : *pPathValues++ = *i;
643 :
644 : // Creating CustomShapeGeometry property
645 123 : std::vector<beans::PropertyValue> aGeomPropVec;
646 62 : if (aViewBox.X || aViewBox.Y || aViewBox.Width || aViewBox.Height)
647 : {
648 3 : aViewBox.Width -= aViewBox.X;
649 3 : aViewBox.Height -= aViewBox.Y;
650 3 : aPropertyValue.Name = "ViewBox";
651 3 : aPropertyValue.Value <<= aViewBox;
652 3 : aGeomPropVec.push_back(aPropertyValue);
653 : }
654 62 : if (aPathPropSeq.getLength())
655 : {
656 3 : aPropertyValue.Name = "Path";
657 3 : aPropertyValue.Value <<= aPathPropSeq;
658 3 : aGeomPropVec.push_back(aPropertyValue);
659 : }
660 123 : uno::Sequence<beans::PropertyValue> aGeomPropSeq(aGeomPropVec.size());
661 62 : beans::PropertyValue* pGeomValues = aGeomPropSeq.getArray();
662 68 : for (std::vector<beans::PropertyValue>::iterator i = aGeomPropVec.begin(); i != aGeomPropVec.end(); ++i)
663 6 : *pGeomValues++ = *i;
664 62 : if (aGeomPropSeq.getLength() && xPropertySet.is())
665 3 : xPropertySet->setPropertyValue("CustomShapeGeometry", uno::Any(aGeomPropSeq));
666 :
667 : // Set position and size
668 62 : if (xShape.is())
669 : {
670 61 : sal_Int32 nLeft = rShape.nLeft;
671 61 : sal_Int32 nTop = rShape.nTop;
672 :
673 70 : bool bInShapeGroup = oGroupLeft && oGroupTop && oGroupRight && oGroupBottom
674 70 : && oRelLeft && oRelTop && oRelRight && oRelBottom;
675 61 : if (bInShapeGroup)
676 : {
677 : // See lclGetAbsPoint() in the VML import: rShape is the group shape, oGroup is its coordinate system, oRel is the relative child shape.
678 9 : sal_Int32 nShapeWidth = rShape.nRight - rShape.nLeft;
679 9 : sal_Int32 nShapeHeight = rShape.nBottom - rShape.nTop;
680 9 : sal_Int32 nCoordSysWidth = *oGroupRight - *oGroupLeft;
681 9 : sal_Int32 nCoordSysHeight = *oGroupBottom - *oGroupTop;
682 9 : double fWidthRatio = static_cast< double >( nShapeWidth ) / nCoordSysWidth;
683 9 : double fHeightRatio = static_cast< double >( nShapeHeight ) / nCoordSysHeight;
684 9 : nLeft = static_cast< sal_Int32 >( rShape.nLeft + fWidthRatio * (*oRelLeft - *oGroupLeft) );
685 9 : nTop = static_cast< sal_Int32 >( rShape.nTop + fHeightRatio * (*oRelTop - *oGroupTop) );
686 : }
687 :
688 61 : if (m_bTextFrame)
689 : {
690 30 : xPropertySet->setPropertyValue("HoriOrientPosition", uno::makeAny(nLeft));
691 30 : xPropertySet->setPropertyValue("VertOrientPosition", uno::makeAny(nTop));
692 : }
693 : else
694 31 : xShape->setPosition(awt::Point(nLeft, nTop));
695 :
696 61 : if (bInShapeGroup)
697 9 : xShape->setSize(awt::Size(*oRelRight - *oRelLeft, *oRelBottom - *oRelTop));
698 : else
699 52 : xShape->setSize(awt::Size(rShape.nRight - rShape.nLeft, rShape.nBottom - rShape.nTop));
700 :
701 61 : if (rShape.nHoriOrientRelation != 0)
702 17 : xPropertySet->setPropertyValue("HoriOrientRelation", uno::makeAny(rShape.nHoriOrientRelation));
703 61 : if (rShape.nVertOrientRelation != 0)
704 16 : xPropertySet->setPropertyValue("VertOrientRelation", uno::makeAny(rShape.nVertOrientRelation));
705 61 : if (rShape.nWrap != -1)
706 43 : xPropertySet->setPropertyValue("Surround", uno::makeAny(text::WrapTextMode(rShape.nWrap)));
707 61 : oox::ModelObjectHelper aModelObjectHelper(m_rImport.getModelFactory());
708 61 : if (aFillModel.moType.has())
709 : {
710 6 : oox::drawingml::ShapePropertyMap aPropMap(aModelObjectHelper);
711 6 : aFillModel.pushToPropMap(aPropMap, m_rImport.getGraphicHelper());
712 : // Sets the FillStyle and FillGradient UNO properties.
713 6 : oox::PropertySet(xShape).setProperties(aPropMap);
714 : }
715 :
716 61 : if (aShadowModel.mbHasShadow)
717 : {
718 12 : oox::drawingml::ShapePropertyMap aPropMap(aModelObjectHelper);
719 12 : aShadowModel.pushToPropMap(aPropMap, m_rImport.getGraphicHelper());
720 : // Sets the ShadowFormat UNO property.
721 12 : oox::PropertySet(xShape).setProperties(aPropMap);
722 : }
723 61 : xPropertySet->setPropertyValue("AnchorType", uno::makeAny(text::TextContentAnchorType_AT_CHARACTER));
724 61 : xPropertySet->setPropertyValue("Opaque", uno::makeAny(bOpaque));
725 61 : if (oRelativeWidth)
726 : {
727 3 : xPropertySet->setPropertyValue("RelativeWidth", uno::makeAny(*oRelativeWidth));
728 3 : xPropertySet->setPropertyValue("RelativeWidthRelation", uno::makeAny(nRelativeWidthRelation));
729 : }
730 61 : if (oRelativeHeight)
731 : {
732 3 : xPropertySet->setPropertyValue("RelativeHeight", uno::makeAny(*oRelativeHeight));
733 3 : xPropertySet->setPropertyValue("RelativeHeightRelation", uno::makeAny(nRelativeHeightRelation));
734 61 : }
735 : }
736 :
737 62 : if (m_rImport.isInBackground())
738 : {
739 1 : RTFSprms aAttributes;
740 1 : aAttributes.set(NS_ooxml::LN_CT_Background_color, RTFValue::Pointer_t(new RTFValue(xPropertySet->getPropertyValue("FillColor").get<sal_Int32>())));
741 2 : writerfilter::Reference<Properties>::Pointer_t const pProperties(new RTFReferenceProperties(aAttributes));
742 1 : m_rImport.Mapper().props(pProperties);
743 :
744 2 : uno::Reference<lang::XComponent> xComponent(xShape, uno::UNO_QUERY);
745 1 : xComponent->dispose();
746 2 : return;
747 : }
748 :
749 : // Send it to dmapper
750 61 : m_rImport.Mapper().startShape(xShape);
751 61 : if (bClose)
752 : {
753 29 : m_rImport.Mapper().endShape();
754 : }
755 183 : m_xShape = xShape;
756 : }
757 :
758 32 : void RTFSdrImport::close()
759 : {
760 32 : m_rImport.Mapper().endShape();
761 32 : }
762 :
763 10 : void RTFSdrImport::append(const OUString& aKey, const OUString& aValue)
764 : {
765 10 : applyProperty(m_xShape, aKey, aValue);
766 10 : }
767 :
768 2 : void RTFSdrImport::appendGroupProperty(const OUString& aKey, const OUString& aValue)
769 : {
770 2 : uno::Reference<drawing::XShape> xShape(m_aParents.top(), uno::UNO_QUERY);
771 2 : if (xShape.is())
772 1 : applyProperty(xShape, aKey, aValue);
773 2 : }
774 :
775 : } // namespace rtftok
776 42 : } // namespace writerfilter
777 :
778 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|