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