Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Initial Developer of the Original Code is
16 : * Miklos Vajna <vmiklos@frugalware.org>
17 : * Portions created by the Initial Developer are Copyright (C) 2011 the
18 : * Initial Developer. All Rights Reserved.
19 : *
20 : * Contributor(s):
21 : *
22 : * Alternatively, the contents of this file may be used under the terms of
23 : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
24 : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
25 : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
26 : * instead of those above.
27 : */
28 :
29 : #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
30 : #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
31 : #include <com/sun/star/drawing/LineStyle.hpp>
32 : #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
33 : #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
34 : #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
35 : #include <com/sun/star/text/WrapTextMode.hpp>
36 : #include <com/sun/star/text/WritingMode.hpp>
37 :
38 : #include <ooxml/resourceids.hxx> // NS_ooxml namespace
39 : #include <filter/msfilter/escherex.hxx>
40 : #include <filter/msfilter/util.hxx>
41 :
42 : #include <dmapper/DomainMapper.hxx>
43 : #include "../dmapper/GraphicHelpers.hxx"
44 : #include <rtfsdrimport.hxx>
45 :
46 : using rtl::OString;
47 : using rtl::OStringBuffer;
48 : using rtl::OUString;
49 : using rtl::OUStringBuffer;
50 : using rtl::OUStringToOString;
51 :
52 : namespace writerfilter {
53 : namespace rtftok {
54 :
55 138 : RTFSdrImport::RTFSdrImport(RTFDocumentImpl& rDocument,
56 : uno::Reference<lang::XComponent> const& xDstDoc)
57 138 : : m_rImport(rDocument)
58 : {
59 138 : uno::Reference<drawing::XDrawPageSupplier> xDrawings(xDstDoc, uno::UNO_QUERY);
60 138 : if (xDrawings.is())
61 127 : m_xDrawPage.set(xDrawings->getDrawPage(), uno::UNO_QUERY);
62 138 : }
63 :
64 276 : RTFSdrImport::~RTFSdrImport()
65 : {
66 276 : }
67 :
68 18 : void RTFSdrImport::createShape(OUString aStr, uno::Reference<drawing::XShape>& xShape, uno::Reference<beans::XPropertySet>& xPropertySet)
69 : {
70 18 : if (m_rImport.getModelFactory().is())
71 17 : xShape.set(m_rImport.getModelFactory()->createInstance(aStr), uno::UNO_QUERY);
72 18 : xPropertySet.set(xShape, uno::UNO_QUERY);
73 18 : }
74 :
75 14 : void RTFSdrImport::resolveDhgt(uno::Reference<beans::XPropertySet> xPropertySet, sal_Int32 nZOrder)
76 : {
77 14 : writerfilter::dmapper::DomainMapper& rMapper = (writerfilter::dmapper::DomainMapper&)m_rImport.Mapper();
78 14 : writerfilter::dmapper::GraphicZOrderHelper* pHelper = rMapper.graphicZOrderHelper();
79 14 : xPropertySet->setPropertyValue("ZOrder", uno::makeAny(pHelper->findZOrder(nZOrder)));
80 14 : pHelper->addItem(xPropertySet, nZOrder);
81 14 : }
82 :
83 11 : void RTFSdrImport::resolveFLine(uno::Reference<beans::XPropertySet> xPropertySet, sal_Int32 nFLine)
84 : {
85 11 : if (nFLine == 0)
86 2 : xPropertySet->setPropertyValue("LineStyle", uno::makeAny(drawing::LineStyle_NONE));
87 11 : }
88 :
89 16 : void RTFSdrImport::resolve(RTFShape& rShape)
90 : {
91 16 : int nType = -1;
92 16 : bool bPib = false;
93 16 : bool bCustom = false;
94 :
95 16 : uno::Reference<drawing::XShape> xShape;
96 16 : uno::Reference<beans::XPropertySet> xPropertySet;
97 : // Create this early, as custom shapes may have properties before the type arrives.
98 16 : createShape("com.sun.star.drawing.CustomShape", xShape, xPropertySet);
99 16 : uno::Any aAny;
100 16 : beans::PropertyValue aPropertyValue;
101 16 : awt::Rectangle aViewBox;
102 16 : std::vector<beans::PropertyValue> aPathPropVec;
103 :
104 537 : for (std::vector< std::pair<rtl::OUString, rtl::OUString> >::iterator i = rShape.aProperties.begin();
105 358 : i != rShape.aProperties.end(); ++i)
106 : {
107 163 : if ( i->first == "shapeType" )
108 : {
109 15 : nType = i->second.toInt32();
110 15 : switch (nType)
111 : {
112 : case 20: // Line
113 2 : createShape("com.sun.star.drawing.LineShape", xShape, xPropertySet);
114 2 : break;
115 : default:
116 13 : bCustom = true;
117 13 : break;
118 : }
119 :
120 : // Defaults
121 15 : aAny <<= (sal_uInt32)0xffffff; // White in Word, kind of blue in Writer.
122 15 : if (xPropertySet.is())
123 15 : xPropertySet->setPropertyValue("FillColor", aAny);
124 : }
125 148 : else if ( i->first == "wzName" )
126 1 : xPropertySet->setPropertyValue("Name", uno::makeAny(i->second));
127 147 : else if ( i->first == "wzDescription" )
128 5 : xPropertySet->setPropertyValue("Description", uno::makeAny(i->second));
129 142 : else if ( i->first == "pib" )
130 : {
131 2 : m_rImport.setDestinationText(i->second);
132 2 : bPib = true;
133 : }
134 140 : else if (i->first == "fillColor" && xPropertySet.is())
135 : {
136 5 : aAny <<= msfilter::util::BGRToRGB(i->second.toInt32());
137 5 : xPropertySet->setPropertyValue("FillColor", aAny);
138 : }
139 135 : else if ( i->first == "fillBackColor" )
140 : ; // Ignore: complementer of fillColor
141 133 : else if (i->first == "lineColor" && xPropertySet.is())
142 : {
143 6 : aAny <<= msfilter::util::BGRToRGB(i->second.toInt32());
144 6 : xPropertySet->setPropertyValue("LineColor", aAny);
145 : }
146 127 : else if ( i->first == "lineBackColor" )
147 : ; // Ignore: complementer of lineColor
148 126 : else if (i->first == "txflTextFlow" && xPropertySet.is())
149 : {
150 2 : if (i->second.toInt32() == 1)
151 : {
152 0 : aAny <<= text::WritingMode_TB_RL;
153 0 : xPropertySet->setPropertyValue("TextWritingMode", aAny);
154 : }
155 : }
156 124 : else if (i->first == "fLine" && xPropertySet.is())
157 1 : resolveFLine(xPropertySet, i->second.toInt32());
158 123 : else if (i->first == "fillOpacity" && xPropertySet.is())
159 : {
160 0 : int opacity = 100 - (i->second.toInt32())*100/65536;
161 0 : aAny <<= uno::makeAny(sal_uInt32(opacity));
162 0 : xPropertySet->setPropertyValue("FillTransparence", aAny);
163 : }
164 123 : else if (i->first == "rotation" && xPropertySet.is())
165 : {
166 0 : aAny <<= i->second.toInt32()*100/65536;
167 0 : xPropertySet->setPropertyValue("RotateAngle", aAny);
168 : }
169 123 : else if (i->first == "lineWidth" && xPropertySet.is())
170 : {
171 :
172 8 : aAny <<= i->second.toInt32()/360;
173 8 : xPropertySet->setPropertyValue("LineWidth", aAny);
174 : }
175 115 : else if ( i->first == "pVerticies" )
176 : {
177 2 : uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aCoordinates;
178 2 : sal_Int32 nSize = 0; // Size of a token (it's value is hardwired in the exporter)
179 2 : sal_Int32 nCount = 0; // Number of tokens
180 2 : sal_Int32 nCharIndex = 0; // Character index
181 2 : sal_Int32 nIndex = 0; // Array index
182 116 : do
183 : {
184 116 : OUString aToken = i->second.getToken(0, ';', nCharIndex);
185 116 : if (!nSize)
186 2 : nSize = aToken.toInt32();
187 114 : else if (!nCount)
188 : {
189 2 : nCount = aToken.toInt32();
190 2 : aCoordinates.realloc(nCount);
191 : }
192 : else
193 : {
194 : // The coordinates are in an (x,y) form.
195 112 : aToken = aToken.copy(1, aToken.getLength() - 2);
196 112 : sal_Int32 nI = 0;
197 112 : sal_Int32 nX = 0;
198 112 : sal_Int32 nY = 0;
199 224 : do
200 : {
201 224 : OUString aPoint = aToken.getToken(0, ',', nI);
202 224 : if (!nX)
203 113 : nX = aPoint.toInt32();
204 : else
205 111 : nY = aPoint.toInt32();
206 : }
207 : while (nI >= 0);
208 112 : aCoordinates[nIndex].First.Value <<= nX;
209 112 : aCoordinates[nIndex].Second.Value <<= nY;
210 112 : nIndex++;
211 116 : }
212 : }
213 : while (nCharIndex >= 0);
214 2 : aPropertyValue.Name = "Coordinates";
215 2 : aPropertyValue.Value <<= aCoordinates;
216 2 : aPathPropVec.push_back(aPropertyValue);
217 : }
218 113 : else if ( i->first == "pSegmentInfo" )
219 : {
220 2 : uno::Sequence<drawing::EnhancedCustomShapeSegment> aSegments;
221 2 : sal_Int32 nSize = 0;
222 2 : sal_Int32 nCount = 0;
223 2 : sal_Int32 nCharIndex = 0;
224 2 : sal_Int32 nIndex = 0;
225 17 : do
226 : {
227 17 : sal_Int32 nSeg = i->second.getToken(0, ';', nCharIndex).toInt32();
228 17 : if (!nSize)
229 2 : nSize = nSeg;
230 15 : else if (!nCount)
231 : {
232 2 : nCount = nSeg;
233 2 : aSegments.realloc(nCount);
234 : }
235 : else
236 : {
237 13 : sal_Int32 nPoints = 1;
238 13 : if (nSeg >= 0x2000 && nSeg < 0x20FF)
239 : {
240 3 : nPoints = nSeg & 0x0FFF;
241 3 : nSeg &= 0xFF00;
242 : }
243 :
244 13 : switch (nSeg)
245 : {
246 : case 0x0001: // lineto
247 0 : aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::LINETO;
248 0 : aSegments[nIndex].Count = sal_Int32(1);
249 0 : break;
250 : case 0x4000: // moveto
251 4 : aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::MOVETO;
252 4 : aSegments[nIndex].Count = sal_Int32(1);
253 4 : break;
254 : case 0x2000: // curveto
255 3 : aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::CURVETO;
256 3 : aSegments[nIndex].Count = sal_Int32(nPoints);
257 3 : break;
258 : case 0xb300: // arcto
259 0 : aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::ARCTO;
260 0 : aSegments[nIndex].Count = sal_Int32(0);
261 0 : break;
262 : case 0xac00:
263 : case 0xaa00: // nofill
264 : case 0xab00: // nostroke
265 : case 0x6001: // close
266 1 : break;
267 : case 0x8000: // end
268 4 : aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
269 4 : aSegments[nIndex].Count = sal_Int32(0);
270 4 : break;
271 : default: // given number of lineto elements
272 1 : aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::LINETO;
273 1 : aSegments[nIndex].Count = nSeg;
274 1 : break;
275 : }
276 13 : nIndex++;
277 : }
278 : }
279 : while (nCharIndex >= 0);
280 2 : aPropertyValue.Name = "Segments";
281 2 : aPropertyValue.Value <<= aSegments;
282 2 : aPathPropVec.push_back(aPropertyValue);
283 : }
284 111 : else if ( i->first == "geoLeft" )
285 2 : aViewBox.X = i->second.toInt32();
286 109 : else if ( i->first == "geoTop" )
287 2 : aViewBox.Y = i->second.toInt32();
288 107 : else if ( i->first == "geoRight" )
289 2 : aViewBox.Width = i->second.toInt32();
290 105 : else if ( i->first == "geoBottom" )
291 2 : aViewBox.Height = i->second.toInt32();
292 103 : else if ( i->first == "dhgt" )
293 4 : resolveDhgt(xPropertySet, i->second.toInt32());
294 : else
295 : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": TODO handle shape property '" <<
296 : OUStringToOString( i->first, RTL_TEXTENCODING_UTF8 ).getStr() << "':'" <<
297 : OUStringToOString( i->second, RTL_TEXTENCODING_UTF8 ).getStr() << "'");
298 : }
299 :
300 16 : if (nType == ESCHER_ShpInst_PictureFrame) // picture frame
301 : {
302 2 : if (bPib)
303 2 : m_rImport.resolvePict(false);
304 16 : return;
305 : }
306 :
307 14 : if (m_xDrawPage.is())
308 13 : m_xDrawPage->add(xShape);
309 14 : if (bCustom && xShape.is())
310 : {
311 11 : uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY);
312 11 : xDefaulter->createCustomShapeDefaults(OUString::valueOf(sal_Int32(nType)));
313 : }
314 :
315 : // Creating Path property
316 14 : uno::Sequence<beans::PropertyValue> aPathPropSeq(aPathPropVec.size());
317 14 : beans::PropertyValue* pPathValues = aPathPropSeq.getArray();
318 18 : for (std::vector<beans::PropertyValue>::iterator i = aPathPropVec.begin(); i != aPathPropVec.end(); ++i)
319 4 : *pPathValues++ = *i;
320 :
321 : // Creating CustomShapeGeometry property
322 14 : std::vector<beans::PropertyValue> aGeomPropVec;
323 14 : if (aViewBox.X || aViewBox.Y || aViewBox.Width || aViewBox.Height)
324 : {
325 2 : aViewBox.Width -= aViewBox.X;
326 2 : aViewBox.Height -= aViewBox.Y;
327 2 : aPropertyValue.Name = "ViewBox";
328 2 : aPropertyValue.Value <<= aViewBox;
329 2 : aGeomPropVec.push_back(aPropertyValue);
330 : }
331 14 : if (aPathPropSeq.getLength())
332 : {
333 2 : aPropertyValue.Name = "Path";
334 2 : aPropertyValue.Value <<= aPathPropSeq;
335 2 : aGeomPropVec.push_back(aPropertyValue);
336 : }
337 14 : uno::Sequence<beans::PropertyValue> aGeomPropSeq(aGeomPropVec.size());
338 14 : beans::PropertyValue* pGeomValues = aGeomPropSeq.getArray();
339 18 : for (std::vector<beans::PropertyValue>::iterator i = aGeomPropVec.begin(); i != aGeomPropVec.end(); ++i)
340 4 : *pGeomValues++ = *i;
341 14 : if (aGeomPropSeq.getLength() && xPropertySet.is())
342 2 : xPropertySet->setPropertyValue("CustomShapeGeometry", uno::Any(aGeomPropSeq));
343 :
344 : // Set position and size
345 14 : if (xShape.is())
346 : {
347 13 : xShape->setPosition(awt::Point(rShape.nLeft, rShape.nTop));
348 13 : xShape->setSize(awt::Size(rShape.nRight - rShape.nLeft, rShape.nBottom - rShape.nTop));
349 13 : if (rShape.nHoriOrientRelation != 0)
350 5 : xPropertySet->setPropertyValue("HoriOrientRelation", uno::makeAny(rShape.nHoriOrientRelation));
351 13 : if (rShape.nVertOrientRelation != 0)
352 4 : xPropertySet->setPropertyValue("VertOrientRelation", uno::makeAny(rShape.nVertOrientRelation));
353 13 : if (rShape.nWrap != -1)
354 10 : xPropertySet->setPropertyValue("Surround", uno::makeAny(text::WrapTextMode(rShape.nWrap)));
355 : }
356 :
357 : // Send it to dmapper
358 14 : m_rImport.Mapper().startShape(xShape);
359 14 : m_rImport.replayShapetext();
360 14 : m_rImport.Mapper().endShape();
361 : }
362 :
363 : } // namespace rtftok
364 15 : } // namespace writerfilter
365 :
366 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|