Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* MWAWImportFilter: Sets up the filter, and calls DocumentCollector
3 : * to do the actual filtering
4 : *
5 : * This file is part of the LibreOffice project.
6 : *
7 : * This Source Code Form is subject to the terms of the Mozilla Public
8 : * License, v. 2.0. If a copy of the MPL was not distributed with this
9 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 : */
11 :
12 : #include <osl/diagnose.h>
13 : #include <rtl/tencinfo.h>
14 :
15 : #include <com/sun/star/io/XInputStream.hpp>
16 : #include <com/sun/star/xml/sax/XAttributeList.hpp>
17 : #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
18 : #include <com/sun/star/xml/sax/InputSource.hpp>
19 : #include <com/sun/star/xml/sax/XParser.hpp>
20 : #include <com/sun/star/io/XSeekable.hpp>
21 : #include <com/sun/star/uno/Reference.h>
22 :
23 : #include <comphelper/componentcontext.hxx>
24 : #include <xmloff/attrlist.hxx>
25 : #include <ucbhelper/content.hxx>
26 :
27 : #include <libmwaw/libmwaw.hxx>
28 : #include <libodfgen/libodfgen.hxx>
29 :
30 : #include "common/DocumentHandler.hxx"
31 : #include "common/WPXSvStream.hxx"
32 : #include "MWAWImportFilter.hxx"
33 :
34 : #include <iostream>
35 :
36 : using namespace ::com::sun::star::uno;
37 : using com::sun::star::uno::Sequence;
38 : using com::sun::star::uno::Reference;
39 : using com::sun::star::uno::Any;
40 : using com::sun::star::uno::UNO_QUERY;
41 : using com::sun::star::uno::XInterface;
42 : using com::sun::star::uno::Exception;
43 : using com::sun::star::uno::RuntimeException;
44 : using com::sun::star::beans::PropertyValue;
45 : using com::sun::star::document::XFilter;
46 : using com::sun::star::document::XExtendedFilterDetection;
47 : using com::sun::star::ucb::XCommandEnvironment;
48 :
49 : using com::sun::star::io::XInputStream;
50 : using com::sun::star::document::XImporter;
51 : using com::sun::star::xml::sax::InputSource;
52 : using com::sun::star::xml::sax::XAttributeList;
53 : using com::sun::star::xml::sax::XDocumentHandler;
54 : using com::sun::star::xml::sax::XParser;
55 :
56 : namespace
57 : {
58 :
59 : //! Internal: creates the string "f pt"
60 0 : static std::string getStringPt(double f)
61 : {
62 0 : std::stringstream s;
63 0 : s << float(f) << "pt";
64 0 : return s.str();
65 : }
66 :
67 0 : static double getSizeInPt(WPXProperty const &prop)
68 : {
69 0 : WPXString str = prop.getStr();
70 0 : if (!str.len()) return 0.0;
71 :
72 : // we have a string, so we can not use getDouble
73 0 : std::istringstream iss(str.cstr());
74 0 : double res = 0.0;
75 0 : iss >> res;
76 :
77 : // try to guess the type
78 : // point->pt, twip->*, inch -> in
79 0 : char c = str.len() ? str.cstr()[str.len()-1] : ' ';
80 0 : if (c == '*') res /= 1440.;
81 0 : else if (c == 't') res /= 72.;
82 0 : else if (c == 'n') ;
83 0 : else if (c == '%')
84 : {
85 : SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::getSizeInPoint: called with a percent property");
86 : }
87 0 : return res *= 72.;
88 : }
89 :
90 0 : static std::string getStringSizeInPt(WPXProperty const &prop)
91 : {
92 0 : return getStringPt(getSizeInPt(prop));
93 : }
94 :
95 0 : static std::string getStyleName(int id)
96 : {
97 0 : std::stringstream s;
98 0 : s.str("");
99 0 : s << "bd" << id+1;
100 0 : return s.str();
101 : }
102 :
103 : } // anonymous namespace
104 :
105 : namespace MWAWObjectHandlerInternal
106 : {
107 0 : class Shape
108 : {
109 : public:
110 0 : Shape() : m_type(BAD), m_styleId(-1), m_w(0), m_h(0), m_rw(0), m_rh(0),
111 0 : m_x(), m_y(), m_angle(), m_path("")
112 : {
113 0 : }
114 : bool read(const char *psName, WPXPropertyList const &xPropList, int styleId);
115 : bool write(OdfDocumentHandler *output) const;
116 : bool ok() const
117 : {
118 : return m_type != BAD;
119 : }
120 :
121 : protected:
122 : bool drawLine(OdfDocumentHandler *output) const;
123 : bool drawRectangle(OdfDocumentHandler *output) const;
124 : bool drawCircle(OdfDocumentHandler *output) const;
125 : bool drawArc(OdfDocumentHandler *output) const;
126 : bool drawPath(OdfDocumentHandler *output) const;
127 : bool drawPolygon(OdfDocumentHandler *output, bool is2D) const;
128 :
129 : enum Type { LINE, RECTANGLE, CIRCLE, ARC, PATH, POLYLINE, POLYGON, BAD } m_type;
130 :
131 : int m_styleId;
132 : double m_w,m_h, m_rw, m_rh;
133 : std::vector<double> m_x,m_y;
134 : std::vector<double> m_angle;
135 : std::string m_path;
136 : };
137 :
138 0 : class Document
139 : {
140 : public:
141 0 : Document() : styles(), shapes(), m_w(0.0), m_h(0.0) {}
142 : bool open(const char *psName, WPXPropertyList const &xPropList);
143 : bool close(const char *psName);
144 :
145 : void characters(WPXString const &sCharacters);
146 :
147 : void write(OdfDocumentHandler *output);
148 :
149 : protected:
150 : static void writeStyle(OdfDocumentHandler *output,
151 : WPXPropertyList const &style, int styleId);
152 :
153 : std::vector<WPXPropertyList> styles;
154 : std::vector<Shape> shapes;
155 :
156 : protected:
157 : double m_w, m_h;
158 : };
159 :
160 : }
161 :
162 : class MWAWObjectHandler : public MWAWPropertyHandler
163 : {
164 : public:
165 0 : MWAWObjectHandler(OdfDocumentHandler *output) : MWAWPropertyHandler(), m_document(), m_output(output) { }
166 0 : ~MWAWObjectHandler() {};
167 :
168 0 : void startDocument()
169 : {
170 0 : m_document= MWAWObjectHandlerInternal::Document();
171 0 : };
172 0 : void endDocument()
173 : {
174 0 : if (m_output) m_document.write(m_output);
175 0 : };
176 :
177 0 : void startElement(const char *psName, const WPXPropertyList &xPropList)
178 : {
179 0 : m_document.open(psName, xPropList);
180 0 : }
181 0 : void endElement(const char *psName)
182 : {
183 0 : m_document.close(psName);
184 0 : }
185 0 : void characters(const WPXString &sCharacters)
186 : {
187 0 : m_document.characters(sCharacters);
188 0 : }
189 :
190 : private:
191 : MWAWObjectHandler(MWAWObjectHandler const &);
192 : MWAWObjectHandler operator=(MWAWObjectHandler const &);
193 :
194 : MWAWObjectHandlerInternal::Document m_document;
195 : OdfDocumentHandler *m_output;
196 : };
197 :
198 :
199 0 : static bool handleEmbeddedMWAWObject(const WPXBinaryData &data, OdfDocumentHandler *pHandler, const OdfStreamType)
200 : {
201 0 : MWAWObjectHandler tmpHandler(pHandler);
202 0 : tmpHandler.startDocument();
203 0 : if (!tmpHandler.checkData(data) || !tmpHandler.readData(data)) return false;
204 0 : tmpHandler.endDocument();
205 0 : return true;
206 : }
207 :
208 0 : bool MWAWObjectHandlerInternal::Shape::read(const char *psName, WPXPropertyList const &xPropList, int stylId)
209 : {
210 0 : m_styleId = stylId;
211 0 : m_type = BAD;
212 0 : if (strcmp(psName,"drawLine")==0) m_type = LINE;
213 0 : else if (strcmp(psName,"drawRectangle")==0) m_type = RECTANGLE;
214 0 : else if (strcmp(psName,"drawCircle")==0) m_type = CIRCLE;
215 0 : else if (strcmp(psName,"drawArc")==0) m_type = ARC;
216 0 : else if (strcmp(psName,"drawPath")==0) m_type = PATH;
217 0 : else if (strcmp(psName,"drawPolyline")==0) m_type = POLYLINE;
218 0 : else if (strcmp(psName,"drawPolygon")==0) m_type = POLYGON;
219 0 : else return false;
220 :
221 0 : WPXPropertyList::Iter i(xPropList);
222 0 : for (i .rewind(); i.next(); )
223 : {
224 0 : if (strcmp(i.key(), "w") == 0) m_w = getSizeInPt(*i());
225 0 : else if (strcmp(i.key(), "h") == 0) m_h = getSizeInPt(*i());
226 0 : else if (strcmp(i.key(), "rw") == 0) m_rw = getSizeInPt(*i());
227 0 : else if (strcmp(i.key(), "rh") == 0) m_rh = getSizeInPt(*i());
228 0 : else if (strcmp(i.key(), "path") == 0)
229 : {
230 0 : if (i()->getStr().len())
231 0 : m_path = i()->getStr().cstr();
232 : }
233 : else
234 : {
235 0 : char const *key = i.key();
236 0 : int len = (int) strlen(key);
237 0 : bool readOk = len > 1, generic = false;
238 0 : std::vector<double> *which = 0L;
239 0 : if (readOk && strncmp(i.key(),"x",1)==0)
240 : {
241 0 : which = &m_x;
242 0 : key++;
243 : }
244 0 : else if (readOk && strncmp(i.key(),"y",1)==0)
245 : {
246 0 : which = &m_y;
247 0 : key++;
248 : }
249 0 : else if (readOk && strncmp(i.key(),"angle",5)==0)
250 : {
251 0 : which = &m_angle;
252 0 : key+=5;
253 0 : readOk = len>5;
254 0 : generic=true;
255 : }
256 0 : else readOk = false;
257 :
258 0 : long w(0);
259 0 : if (readOk)
260 : {
261 : char *res;
262 0 : w = strtol(key, &res, 10);
263 0 : readOk = (*res=='\0') && (w >= 0);
264 : }
265 0 : if (readOk)
266 : {
267 0 : if (int(which->size()) < w+1) which->resize(size_t(w)+1,0.0);
268 0 : double unit = generic ? 1./72.0 : 1.0;
269 0 : (*which)[size_t(w)] = getSizeInPt(*i()) * unit;
270 : }
271 0 : if (!readOk)
272 : {
273 : SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::read: find an unknown key '" << i.key() << "'");
274 : }
275 : }
276 : }
277 :
278 0 : return true;
279 : }
280 :
281 0 : bool MWAWObjectHandlerInternal::Shape::write(OdfDocumentHandler *output) const
282 : {
283 0 : if (!output) return true;
284 0 : if (m_type == LINE) return drawLine(output);
285 0 : else if (m_type == RECTANGLE) return drawRectangle(output);
286 0 : else if (m_type == CIRCLE) return drawCircle(output);
287 0 : else if (m_type == ARC) return drawArc(output);
288 0 : else if (m_type == PATH) return drawPath(output);
289 0 : else if (m_type == POLYLINE) return drawPolygon(output, false);
290 0 : else if (m_type == POLYGON) return drawPolygon(output, true);
291 :
292 0 : return false;
293 : }
294 :
295 0 : bool MWAWObjectHandlerInternal::Shape::drawLine(OdfDocumentHandler *output) const
296 : {
297 0 : if (m_x.size() < 2 || m_y.size() < 2)
298 : {
299 : SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::drawLine: PB");
300 0 : return false;
301 : }
302 :
303 0 : WPXPropertyList list;
304 0 : list.insert("draw:text-style-name","P1");
305 0 : list.insert("draw:layer","layout");
306 0 : list.insert("draw:style-name",getStyleName(m_styleId).c_str());
307 0 : list.insert("svg:x1",getStringPt(m_x[0]).c_str());
308 0 : list.insert("svg:y1",getStringPt(m_y[0]).c_str());
309 0 : list.insert("svg:x2",getStringPt(m_x[1]).c_str());
310 0 : list.insert("svg:y2",getStringPt(m_y[1]).c_str());
311 0 : output->startElement("draw:line", list);
312 0 : output->endElement("draw:line");
313 0 : return true;
314 : }
315 :
316 0 : bool MWAWObjectHandlerInternal::Shape::drawRectangle(OdfDocumentHandler *output) const
317 : {
318 0 : if (m_x.size() < 1 || m_y.size() < 1)
319 : {
320 : SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::drawRectangle: PB");
321 0 : return false;
322 : }
323 :
324 0 : WPXPropertyList list;
325 0 : list.insert("draw:text-style-name","P1");
326 0 : list.insert("draw:layer","layout");
327 0 : list.insert("draw:style-name",getStyleName(m_styleId).c_str());
328 0 : list.insert("svg:x",getStringPt(m_x[0]).c_str());
329 0 : list.insert("svg:y",getStringPt(m_y[0]).c_str());
330 0 : list.insert("svg:width",getStringPt(m_w).c_str());
331 0 : list.insert("svg:height",getStringPt(m_h).c_str());
332 :
333 0 : if (m_rw <= 0.0 || m_rh <= 0.0 || m_w < 2*m_rw || m_h < 2*m_rh)
334 : {
335 0 : if (m_rw > 0.0 || m_rh > 0.0)
336 : {
337 : SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::drawRectangle:: can only create a rectangle");
338 : }
339 0 : output->startElement("draw:rect", list);
340 0 : output->endElement("draw:rect");
341 0 : return true;
342 : }
343 :
344 : // ok, we draw a rond rect
345 0 : std::stringstream s;
346 0 : float const unit = 1.0;//35.3;
347 0 : s.str("");
348 :
349 0 : double const minPt[] = { m_x[0] *unit, m_y[0] *unit };
350 0 : double const maxPt[] = { (m_w+m_x[0]) *unit, (m_h+m_y[0]) *unit };
351 :
352 0 : s << "0 0 " << int(maxPt[0]) << " " << int(maxPt[1]);
353 0 : list.insert("svg:viewBox", s.str().c_str());
354 :
355 0 : double const W[] = { m_rw *unit, m_rh *unit };
356 0 : double const xPt[] = { minPt[0]+W[0], maxPt[0]-W[0], maxPt[0],
357 0 : maxPt[0], maxPt[0], maxPt[0],
358 0 : maxPt[0]-W[0], minPt[0]+W[0], minPt[0],
359 0 : minPt[0], minPt[0], minPt[0],
360 0 : minPt[0]+W[0]
361 0 : };
362 0 : double const yPt[] = { minPt[1], minPt[1], minPt[1],
363 0 : minPt[1]+W[1], maxPt[1]-W[1], maxPt[1],
364 0 : maxPt[1], maxPt[1], maxPt[1],
365 0 : maxPt[1]-W[1], minPt[1]+W[1], minPt[1],
366 0 : minPt[1]
367 0 : };
368 0 : s.str("");
369 0 : for (int i = 0; i < 13; i++)
370 : {
371 0 : if (i) s << " ";
372 :
373 0 : if (i == 0) s << "M";
374 0 : else if ((i%3) == 2) s << "Q";
375 0 : else if ((i%3) == 0);
376 0 : else s << "L";
377 0 : s << int(xPt[i]) << " " << int(yPt[i]);
378 : }
379 0 : s << "Z";
380 0 : list.insert("svg:d", s.str().c_str());
381 :
382 0 : output->startElement("draw:path", list);
383 0 : output->endElement("draw:path");
384 0 : return true;
385 : }
386 :
387 0 : bool MWAWObjectHandlerInternal::Shape::drawCircle(OdfDocumentHandler *output) const
388 : {
389 0 : if (m_x.size() < 1 || m_y.size() < 1)
390 : {
391 : SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::drawCircle: PB");
392 0 : return false;
393 : }
394 :
395 0 : WPXPropertyList list;
396 0 : list.insert("draw:text-style-name","P1");
397 0 : list.insert("draw:layer","layout");
398 0 : list.insert("draw:style-name",getStyleName(m_styleId).c_str());
399 0 : list.insert("svg:x",getStringPt(m_x[0]).c_str());
400 0 : list.insert("svg:y",getStringPt(m_y[0]).c_str());
401 0 : list.insert("svg:width",getStringPt(m_w).c_str());
402 0 : list.insert("svg:height",getStringPt(m_h).c_str());
403 0 : if (m_w < m_h || m_w > m_h)
404 : {
405 0 : output->startElement("draw:ellipse", list);
406 0 : output->endElement("draw:ellipse");
407 : }
408 : else
409 : {
410 0 : output->startElement("draw:circle", list);
411 0 : output->endElement("draw:circle");
412 : }
413 0 : return true;
414 : }
415 :
416 0 : bool MWAWObjectHandlerInternal::Shape::drawArc(OdfDocumentHandler *output) const
417 : {
418 0 : if (m_angle.size() < 2)
419 : {
420 : SAL_INFO("writerperfect", "MWAWObjectHandlerInternal::Shape::drawArc: angle are filled, call draw Circle");
421 0 : return drawCircle(output);
422 : }
423 0 : if (m_x.size() < 1 || m_y.size() < 1)
424 : {
425 : SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::drawArc: PB");
426 0 : return false;
427 : }
428 :
429 0 : WPXPropertyList list;
430 0 : list.insert("draw:text-style-name","P1");
431 0 : list.insert("draw:layer","layout");
432 0 : list.insert("draw:style-name",getStyleName(m_styleId).c_str());
433 0 : list.insert("svg:x",getStringPt(m_x[0]).c_str());
434 0 : list.insert("svg:y",getStringPt(m_y[0]).c_str());
435 0 : list.insert("svg:width",getStringPt(m_w).c_str());
436 0 : list.insert("svg:height",getStringPt(m_h).c_str());
437 0 : list.insert("draw:kind","arc");
438 :
439 0 : std::stringstream s;
440 : // odg prefers angle between -360 and +360, ...
441 0 : int minAngl = int(m_angle[0]), maxAngl = int(m_angle[1]);
442 0 : if (minAngl >= 360 || maxAngl >= 360)
443 : {
444 0 : minAngl -= 360;
445 0 : maxAngl -= 360;
446 : }
447 0 : s.str("");
448 0 : s << minAngl;
449 0 : list.insert("draw:start-angle", s.str().c_str());
450 0 : s.str("");
451 0 : s << maxAngl;
452 0 : list.insert("draw:end-angle", s.str().c_str());
453 :
454 0 : if (m_w < m_h || m_w > m_h)
455 : {
456 0 : output->startElement("draw:ellipse", list);
457 0 : output->endElement("draw:ellipse");
458 : }
459 : else
460 : {
461 0 : output->startElement("draw:circle", list);
462 0 : output->endElement("draw:circle");
463 : }
464 0 : return true;
465 : }
466 :
467 0 : bool MWAWObjectHandlerInternal::Shape::drawPolygon(OdfDocumentHandler *output, bool is2D) const
468 : {
469 0 : if (m_x.size() < 1 || m_y.size() != m_x.size())
470 : {
471 : SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::drawPolygon: PB");
472 0 : return false;
473 : }
474 0 : std::stringstream s;
475 0 : WPXPropertyList list;
476 0 : list.insert("draw:text-style-name","P1");
477 0 : list.insert("draw:layer","layout");
478 0 : list.insert("draw:style-name","bd1");
479 0 : list.insert("svg:x","0pt");
480 0 : list.insert("svg:y","0pt");
481 0 : list.insert("svg:width",getStringPt(m_w).c_str());
482 0 : list.insert("svg:height",getStringPt(m_h).c_str());
483 :
484 0 : size_t numPt = m_x.size();
485 :
486 0 : float const unit = 1; //35.2777; // convert in centimeters
487 0 : s.str("");
488 0 : s << "0 0 " << int(m_w*unit) << " " << int(m_h*unit);
489 0 : list.insert("svg:viewBox", s.str().c_str());
490 :
491 0 : s.str("");
492 0 : for (size_t i = 0; i < numPt; i++)
493 : {
494 0 : if (i) s << " ";
495 0 : s << int(m_x[i]*unit) << "," << int(m_y[i]*unit);
496 : }
497 0 : list.insert("draw:points", s.str().c_str());
498 0 : if (!is2D)
499 : {
500 0 : output->startElement("draw:polyline", list);
501 0 : output->endElement("draw:polyline");
502 : }
503 : else
504 : {
505 0 : output->startElement("draw:polygon", list);
506 0 : output->endElement("draw:polygon");
507 : }
508 0 : return true;
509 : }
510 :
511 0 : bool MWAWObjectHandlerInternal::Shape::drawPath(OdfDocumentHandler *output) const
512 : {
513 0 : if (m_path.length()==0 || m_w <= 0 || m_h <= 0)
514 : {
515 : SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::drawPath: PB");
516 0 : return false;
517 : }
518 :
519 0 : WPXPropertyList list;
520 0 : list.insert("draw:text-style-name","P1");
521 0 : list.insert("draw:layer","layout");
522 0 : list.insert("draw:style-name",getStyleName(m_styleId).c_str());
523 0 : list.insert("svg:x","0pt");
524 0 : list.insert("svg:y","0pt");
525 0 : list.insert("svg:width",getStringPt(m_w).c_str());
526 0 : list.insert("svg:height",getStringPt(m_h).c_str());
527 0 : std::stringstream s;
528 0 : s << "0 0 " << int(m_w) << " " << int(m_h);
529 0 : list.insert("svg:viewBox", s.str().c_str());
530 0 : list.insert("svg:d",m_path.c_str());
531 :
532 0 : output->startElement("draw:path", list);
533 0 : output->endElement("draw:path");
534 0 : return true;
535 : }
536 :
537 :
538 0 : bool MWAWObjectHandlerInternal::Document::open(const char *psName, WPXPropertyList const &xPropList)
539 : {
540 0 : if (strncmp(psName,"libmwaw:", 8) == 0)
541 0 : psName += 8;
542 : else
543 : {
544 : SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Document::open Unknown tag '" << psName << "'.." );
545 0 : return false;
546 : }
547 0 : if (strcmp(psName, "document") == 0)
548 : {
549 0 : m_w = m_h = 0.;
550 0 : WPXPropertyList::Iter i(xPropList);
551 0 : for (i .rewind(); i.next(); )
552 : {
553 0 : if (strcmp(i.key(), "w") == 0) m_w = getSizeInPt(*i());
554 0 : else if (strcmp(i.key(), "h") == 0) m_h = getSizeInPt(*i());
555 : else
556 : {
557 : SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Document::open: find an unknown key '" << i.key() << "'");
558 : }
559 : }
560 0 : return true;
561 : }
562 0 : else if (strcmp(psName, "graphicStyle") == 0)
563 : {
564 0 : styles.push_back(xPropList);
565 0 : return true;
566 : }
567 : else
568 : {
569 0 : int id = int(styles.size());
570 0 : Shape shape;
571 0 : if (shape.read(psName, xPropList, id ? id-1 : 0))
572 : {
573 0 : if (id == 0)
574 : {
575 : SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Document::open shape created without style..");
576 0 : styles.push_back(WPXPropertyList());
577 : }
578 0 : shapes.push_back(shape);
579 0 : return true;
580 0 : }
581 : }
582 : SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Document::open Unknown tag '" << psName << "'..");
583 0 : return false;
584 : }
585 :
586 0 : bool MWAWObjectHandlerInternal::Document::close(const char *)
587 : {
588 0 : return true;
589 : }
590 :
591 0 : void MWAWObjectHandlerInternal::Document::characters(WPXString const &)
592 : {
593 : SAL_WARN("writerperfect", "Document::characters must NOT be called..");
594 0 : }
595 :
596 0 : void MWAWObjectHandlerInternal::Document::write(OdfDocumentHandler *output)
597 : {
598 0 : if (!output) return;
599 0 : WPXPropertyList list;
600 0 : std::stringstream s;
601 :
602 0 : list.clear();
603 0 : list.insert("office:mimetype","application/vnd.oasis.opendocument.graphics");
604 0 : list.insert("office:version", "1.0");
605 :
606 0 : list.insert("xmlns:config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0");
607 0 : list.insert("xmlns:dc", "http://purl.org/dc/elements/1.1/");
608 0 : list.insert("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0");
609 0 : list.insert("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0");
610 0 : list.insert("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0");
611 0 : list.insert("xmlns:ooo", "http://openoffice.org/2004/office");
612 0 : list.insert("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0");
613 0 : list.insert("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0");
614 0 : list.insert("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0");
615 :
616 0 : output->startElement("office:document", list);
617 :
618 : // SETTINGS
619 : {
620 0 : list.clear();
621 0 : output->startElement("office:settings", list);
622 0 : list.clear();
623 0 : list.insert("config:name","ooo:view-settings");
624 0 : output->startElement("config:config-item-set", list);
625 :
626 : // - Top
627 0 : list.clear();
628 0 : list.insert("config:name","VisibleAreaTop");
629 0 : list.insert("config:type","int");
630 0 : output->startElement("config:config-item", list);
631 0 : output->characters("0");
632 :
633 0 : output->endElement("config:config-item");
634 : // - Left
635 0 : list.clear();
636 0 : list.insert("config:name","VisibleAreaLeft");
637 0 : list.insert("config:type","int");
638 0 : output->startElement("config:config-item", list);
639 0 : output->characters("0");
640 0 : output->endElement("config:config-item");
641 : // - Width
642 0 : list.clear();
643 0 : list.insert("config:name","VisibleAreaWidth");
644 0 : list.insert("config:type","int");
645 0 : s.str("");
646 0 : s << int(m_w*35.2777); // *2540/72. why ?
647 0 : output->startElement("config:config-item", list);
648 0 : output->characters(s.str().c_str());
649 0 : output->endElement("config:config-item");
650 : // - Height
651 0 : list.clear();
652 0 : list.insert("config:name","VisibleAreaHeight");
653 0 : list.insert("config:type","int");
654 0 : s.str("");
655 0 : s << int(m_h*35.2777); // *2540/72. why ?
656 0 : output->startElement("config:config-item", list);
657 0 : output->characters(s.str().c_str());
658 0 : output->endElement("config:config-item");
659 :
660 0 : output->endElement("config:config-item-set");
661 0 : output->endElement("office:settings");
662 : }
663 :
664 : // STYLES
665 : {
666 0 : list.clear();
667 0 : output->startElement("office:styles", list);
668 : // - a gradient
669 0 : list.clear();
670 0 : list.insert("draw:angle","0");
671 0 : list.insert("draw:border","0%");
672 0 : list.insert("draw:end-color","#000000");
673 0 : list.insert("draw:end-intensity","100%");
674 0 : list.insert("draw:name","Gradient_1");
675 0 : list.insert("draw:start-color","#000000");
676 0 : list.insert("draw:start-intensity","100%");
677 0 : list.insert("draw:style","linear");
678 0 : output->startElement("draw:gradient", list);
679 0 : output->endElement("draw:gradient");
680 : // - an arrow
681 0 : list.clear();
682 0 : list.insert("draw:name","Arrow");
683 0 : list.insert("svg:viewBox","0 0 20 30");
684 0 : list.insert("svg:d","m10 0-10 30h20z");
685 0 : output->startElement("draw:marker", list);
686 0 : output->endElement("draw:marker");
687 :
688 0 : output->endElement("office:styles");
689 : }
690 :
691 : // AUTOMATIC STYLES
692 : {
693 0 : list.clear();
694 0 : output->startElement("office:automatic-styles", list);
695 :
696 : // - PM0
697 : {
698 0 : list.clear();
699 0 : list.insert("style:name","PM0");
700 0 : output->startElement("style:page-layout", list);
701 0 : list.clear();
702 0 : list.insert("fo:margin-bottom","0in");
703 0 : list.insert("fo:margin-left","0in");
704 0 : list.insert("fo:margin-right","0in");
705 0 : list.insert("fo:margin-top","0in");
706 0 : list.insert("fo:page-height",getStringPt(m_h).c_str());
707 0 : list.insert("fo:page-width",getStringPt(m_w).c_str());
708 0 : list.insert("style:print-orientation","portrait");
709 0 : output->startElement("style:page-layout-properties", list);
710 0 : output->endElement("style:page-layout-properties");
711 0 : output->endElement("style:page-layout");
712 : }
713 :
714 : // - dp1
715 : {
716 0 : list.clear();
717 0 : list.insert("style:family","drawing-page");
718 0 : list.insert("style:name","dp1");
719 0 : output->startElement("style:style", list);
720 0 : list.clear();
721 0 : list.insert("draw:fill","none");
722 0 : output->startElement("style:drawing-page-properties", list);
723 0 : output->endElement("style:drawing-page-properties");
724 0 : output->endElement("style:style");
725 : }
726 :
727 : // -- the styles
728 0 : for (size_t i = 0; i < styles.size() ; i++)
729 0 : writeStyle(output, styles[i], int(i));
730 :
731 0 : output->endElement("office:automatic-styles");
732 : }
733 :
734 : // MASTER STYLES
735 : {
736 0 : list.clear();
737 0 : output->startElement("office:master-styles", list);
738 0 : list.clear();
739 0 : list.insert("draw:style-name","dp1");
740 0 : list.insert("style:name","Default");
741 0 : list.insert("style:page-layout-name","PM0");
742 0 : output->startElement("style:master-page", list);
743 0 : output->endElement("style:master-page");
744 0 : output->endElement("office:master-styles");
745 : }
746 :
747 : // BODY
748 : {
749 0 : list.clear();
750 0 : output->startElement("office:body", list);
751 0 : output->startElement("office:drawing", list);
752 : {
753 0 : list.clear();
754 0 : list.insert("draw:master-page-name","Default");
755 0 : list.insert("draw:name","page1");
756 0 : list.insert("draw:style-name","dp1");
757 :
758 0 : output->startElement("draw:page", list);
759 :
760 0 : for (size_t i = 0; i < shapes.size() ; i++)
761 0 : shapes[i].write(output);
762 :
763 0 : output->endElement("draw:page");
764 : }
765 0 : output->endElement("office:drawing");
766 0 : output->endElement("office:body");
767 : }
768 0 : output->endElement("office:document");
769 : }
770 :
771 0 : void MWAWObjectHandlerInternal::Document::writeStyle (OdfDocumentHandler *output, WPXPropertyList const &style, int styleId)
772 : {
773 0 : if (!output) return;
774 :
775 0 : WPXPropertyList list;
776 0 : list.clear();
777 0 : list.insert("style:family","graphic");
778 0 : list.insert("style:name",getStyleName(styleId).c_str());
779 0 : list.insert("style:parent-style-name","standard");
780 0 : output->startElement("style:style", list);
781 : {
782 0 : list.clear();
783 :
784 0 : WPXPropertyList::Iter i(style);
785 0 : for (i .rewind(); i.next(); )
786 : {
787 0 : if (strcmp(i.key(), "lineColor") == 0)
788 0 : list.insert("svg:stroke-color", i()->getStr().cstr());
789 0 : else if (strcmp(i.key(), "lineWidth") == 0)
790 0 : list.insert("svg:stroke-width", getStringSizeInPt(*i()).c_str());
791 0 : else if (strcmp(i.key(), "lineFill") == 0)
792 0 : list.insert("draw:stroke", i()->getStr().cstr());
793 0 : else if (strcmp(i.key(), "surfaceColor") == 0)
794 0 : list.insert("draw:fill-color", i()->getStr().cstr());
795 0 : else if (strcmp(i.key(), "surfaceFill") == 0)
796 0 : list.insert("draw:fill", i()->getStr().cstr());
797 0 : else if (strcmp(i.key(), "startArrow") == 0)
798 : {
799 0 : if (strcmp(i()->getStr().cstr(), "true") == 0)
800 : {
801 0 : list.insert("draw:marker-start", "Arrow");
802 0 : list.insert("draw:marker-start-center", "false");
803 : }
804 : }
805 0 : else if (strcmp(i.key(), "startArrowWidth") == 0)
806 0 : list.insert("draw:marker-start-width", getStringSizeInPt(*i()).c_str());
807 0 : else if (strcmp(i.key(), "endArrow") == 0)
808 : {
809 0 : if (strcmp(i()->getStr().cstr(), "true") == 0)
810 : {
811 0 : list.insert("draw:marker-end", "Arrow");
812 0 : list.insert("draw:marker-end-center", "false");
813 : }
814 : }
815 0 : else if (strcmp(i.key(), "endArrowWidth") == 0)
816 0 : list.insert("draw:marker-end-width", getStringSizeInPt(*i()).c_str());
817 : else
818 : {
819 : SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Document::writeStyle: find an unknown key '" << i.key() << "'");
820 : }
821 : }
822 :
823 0 : output->startElement("style:graphic-properties", list);
824 0 : output->endElement("style:graphic-properties");
825 : }
826 0 : output->endElement("style:style");
827 : }
828 :
829 :
830 0 : sal_Bool SAL_CALL MWAWImportFilter::importImpl( const Sequence< ::com::sun::star::beans::PropertyValue > &aDescriptor )
831 : throw (RuntimeException)
832 : {
833 : SAL_INFO("writerperfect", "MWAWImportFilter::importImpl");
834 :
835 0 : sal_Int32 nLength = aDescriptor.getLength();
836 0 : const PropertyValue *pValue = aDescriptor.getConstArray();
837 0 : Reference < XInputStream > xInputStream;
838 0 : for ( sal_Int32 i = 0 ; i < nLength; i++)
839 : {
840 0 : if ( pValue[i].Name == "InputStream" )
841 0 : pValue[i].Value >>= xInputStream;
842 : }
843 0 : if ( !xInputStream.is() )
844 : {
845 : OSL_ASSERT( 0 );
846 0 : return sal_False;
847 : }
848 :
849 : // An XML import service: what we push sax messages to..
850 0 : OUString sXMLImportService ( "com.sun.star.comp.Writer.XMLOasisImporter" );
851 0 : Reference < XDocumentHandler > xInternalHandler( comphelper::ComponentContext( mxContext ).createComponent( sXMLImportService ), UNO_QUERY );
852 :
853 : // The XImporter sets up an empty target document for XDocumentHandler to write to..
854 0 : Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY);
855 0 : xImporter->setTargetDocument(mxDoc);
856 :
857 : // OO Document Handler: abstract class to handle document SAX messages, concrete implementation here
858 : // writes to in-memory target doc
859 0 : DocumentHandler xHandler(xInternalHandler);
860 :
861 0 : WPXSvInputStream input( xInputStream );
862 :
863 0 : OdtGenerator collector(&xHandler, ODF_FLAT_XML);
864 0 : collector.registerEmbeddedObjectHandler("image/mwaw-odg", &handleEmbeddedMWAWObject);
865 0 : if (MWAW_OK == MWAWDocument::parse(&input, &collector))
866 0 : return sal_True;
867 0 : return sal_False;
868 : }
869 :
870 0 : sal_Bool SAL_CALL MWAWImportFilter::filter( const Sequence< ::com::sun::star::beans::PropertyValue > &aDescriptor )
871 : throw (RuntimeException)
872 : {
873 : SAL_INFO("writerperfect", "MWAWImportFilter::filter");
874 0 : return importImpl ( aDescriptor );
875 : }
876 0 : void SAL_CALL MWAWImportFilter::cancel( )
877 : throw (RuntimeException)
878 : {
879 : SAL_INFO("writerperfect", "MWAWImportFilter::cancel");
880 0 : }
881 :
882 : // XImporter
883 0 : void SAL_CALL MWAWImportFilter::setTargetDocument( const Reference< ::com::sun::star::lang::XComponent > &xDoc )
884 : throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException)
885 : {
886 : SAL_INFO("writerperfect", "MWAWImportFilter::getTargetDocument");
887 0 : mxDoc = xDoc;
888 0 : }
889 :
890 : // XExtendedFilterDetection
891 72 : OUString SAL_CALL MWAWImportFilter::detect( com::sun::star::uno::Sequence< PropertyValue > &Descriptor )
892 : throw( com::sun::star::uno::RuntimeException )
893 : {
894 : SAL_INFO("writerperfect", "MWAWImportFilter::detect");
895 :
896 72 : MWAWConfidence confidence = MWAW_CONFIDENCE_NONE;
897 72 : MWAWDocument::DocumentType docType = MWAWDocument::UNKNOWN;
898 72 : MWAWDocument::DocumentKind docKind = MWAWDocument::K_UNKNOWN;
899 72 : OUString sTypeName;
900 72 : sal_Int32 nLength = Descriptor.getLength();
901 72 : sal_Int32 location = nLength;
902 72 : const PropertyValue *pValue = Descriptor.getConstArray();
903 144 : Reference < XInputStream > xInputStream;
904 648 : for ( sal_Int32 i = 0 ; i < nLength; i++)
905 : {
906 576 : if ( pValue[i].Name == "TypeName" )
907 72 : location=i;
908 504 : else if ( pValue[i].Name == "InputStream" )
909 72 : pValue[i].Value >>= xInputStream;
910 : }
911 :
912 72 : if (!xInputStream.is())
913 0 : return OUString();
914 :
915 144 : WPXSvInputStream input( xInputStream );
916 :
917 72 : confidence = MWAWDocument::isFileFormatSupported(&input, docType, docKind);
918 :
919 72 : if ((confidence == MWAW_CONFIDENCE_EXCELLENT) || (confidence == MWAW_CONFIDENCE_GOOD))
920 : {
921 0 : if ( docKind == MWAWDocument::K_TEXT )
922 : {
923 0 : switch (docType)
924 : {
925 : case MWAWDocument::ACT: // Acta (nothing done )
926 0 : break;
927 : case MWAWDocument::CW: // ClarisWorks/AppleWorks document (basic)
928 0 : sTypeName = "writer_ClarisWorks";
929 0 : break;
930 : case MWAWDocument::DM: // DocMaker (v4)
931 0 : sTypeName = "writer_DocMaker";
932 0 : break;
933 : case MWAWDocument::ED: // eDOC (v2)
934 0 : sTypeName = "writer_eDoc_Document";
935 0 : break;
936 : case MWAWDocument::FULLW: // FullWrite Professional (basic)
937 0 : sTypeName = "writer_FullWrite_Professional";
938 0 : break;
939 : case MWAWDocument::HMAC: // HanMac Word-K (basic done)
940 0 : sTypeName = "writer_HanMac_Word_K";
941 0 : break;
942 : case MWAWDocument::HMACJ: // HanMac Word-J ( almost nothing done for J document)
943 : // sTypeName = "writer_HanMac_Word_J";
944 0 : break;
945 : case MWAWDocument::LWTEXT: // LightWayText ( only v4.5 Mac format )
946 0 : sTypeName = "writer_LightWayText";
947 0 : break;
948 : case MWAWDocument::MARIW: // Mariner Write ( only v1.6-v3.5 Mac Classic)
949 0 : sTypeName = "writer_Mariner_Write";
950 0 : break;
951 : case MWAWDocument::MINDW: // MindWrite
952 0 : sTypeName = "writer_MindWrite";
953 0 : break;
954 : case MWAWDocument::MW: // MacWrite document
955 0 : sTypeName = "writer_MacWrite";
956 0 : break;
957 : case MWAWDocument::MWPRO: // MacWriteII or MacWritePro document
958 0 : sTypeName = "writer_MacWritePro";
959 0 : break;
960 : case MWAWDocument::MSWORD: // MSWord document (v4 v5: basic done)
961 0 : sTypeName = "writer_Mac_Word";
962 0 : break;
963 : case MWAWDocument::MSWORKS: // MSWorks document (v1 v2)
964 0 : sTypeName = "writer_Mac_Works";
965 0 : break;
966 : case MWAWDocument::NISUSW: // Nisus Writer document: v3.4-v6.5
967 0 : sTypeName = "writer_Nisus_Writer";
968 0 : break;
969 : case MWAWDocument::TEACH: // TeachText or SimpleText: v1
970 0 : sTypeName = "writer_TeachText";
971 0 : break;
972 : case MWAWDocument::TEDIT: // Tex-Edit v2
973 0 : sTypeName = "writer_TexEdit";
974 0 : break;
975 : case MWAWDocument::WNOW: // WriteNow
976 0 : sTypeName = "writer_WriteNow";
977 0 : break;
978 : case MWAWDocument::WPLUS: // writerplus document
979 0 : sTypeName = "writer_WriterPlus";
980 0 : break;
981 : case MWAWDocument::ZWRT: // Z-Write : v1.3
982 0 : sTypeName = "writer_ZWrite";
983 0 : break;
984 : default:
985 0 : break;
986 : }
987 : }
988 : }
989 :
990 72 : if (!sTypeName.isEmpty())
991 : {
992 0 : if ( location == nLength )
993 : {
994 0 : Descriptor.realloc(nLength+1);
995 0 : Descriptor[location].Name = "TypeName";
996 : }
997 :
998 0 : Descriptor[location].Value <<=sTypeName;
999 : }
1000 :
1001 144 : return sTypeName;
1002 : }
1003 :
1004 :
1005 : // XInitialization
1006 0 : void SAL_CALL MWAWImportFilter::initialize( const Sequence< Any > &aArguments )
1007 : throw (Exception, RuntimeException)
1008 : {
1009 : SAL_INFO("writerperfect", "MWAWImportFilter::initialize");
1010 0 : Sequence < PropertyValue > aAnySeq;
1011 0 : sal_Int32 nLength = aArguments.getLength();
1012 0 : if ( nLength && ( aArguments[0] >>= aAnySeq ) )
1013 : {
1014 0 : const PropertyValue *pValue = aAnySeq.getConstArray();
1015 0 : nLength = aAnySeq.getLength();
1016 0 : for ( sal_Int32 i = 0 ; i < nLength; i++)
1017 : {
1018 0 : if ( pValue[i].Name == "Type" )
1019 : {
1020 0 : pValue[i].Value >>= msFilterName;
1021 0 : break;
1022 : }
1023 : }
1024 0 : }
1025 0 : }
1026 2 : OUString MWAWImportFilter_getImplementationName ()
1027 : throw (RuntimeException)
1028 : {
1029 2 : return OUString ( "com.sun.star.comp.Writer.MWAWImportFilter" );
1030 : }
1031 :
1032 : #define SERVICE_NAME1 "com.sun.star.document.ImportFilter"
1033 : #define SERVICE_NAME2 "com.sun.star.document.ExtendedTypeDetection"
1034 0 : sal_Bool SAL_CALL MWAWImportFilter_supportsService( const OUString &ServiceName )
1035 : throw (RuntimeException)
1036 : {
1037 0 : return ( ServiceName == SERVICE_NAME1 || ServiceName == SERVICE_NAME2 );
1038 : }
1039 2 : Sequence< OUString > SAL_CALL MWAWImportFilter_getSupportedServiceNames( )
1040 : throw (RuntimeException)
1041 : {
1042 2 : Sequence < OUString > aRet(2);
1043 2 : OUString *pArray = aRet.getArray();
1044 2 : pArray[0] = OUString ( SERVICE_NAME1 );
1045 2 : pArray[1] = OUString ( SERVICE_NAME2 );
1046 2 : return aRet;
1047 : }
1048 : #undef SERVICE_NAME2
1049 : #undef SERVICE_NAME1
1050 :
1051 72 : Reference< XInterface > SAL_CALL MWAWImportFilter_createInstance( const Reference< XComponentContext > &rContext)
1052 : throw( Exception )
1053 : {
1054 72 : return (cppu::OWeakObject *) new MWAWImportFilter( rContext );
1055 : }
1056 :
1057 : // XServiceInfo
1058 0 : OUString SAL_CALL MWAWImportFilter::getImplementationName( )
1059 : throw (RuntimeException)
1060 : {
1061 0 : return MWAWImportFilter_getImplementationName();
1062 : }
1063 0 : sal_Bool SAL_CALL MWAWImportFilter::supportsService( const OUString &rServiceName )
1064 : throw (RuntimeException)
1065 : {
1066 0 : return MWAWImportFilter_supportsService( rServiceName );
1067 : }
1068 0 : Sequence< OUString > SAL_CALL MWAWImportFilter::getSupportedServiceNames( )
1069 : throw (RuntimeException)
1070 : {
1071 0 : return MWAWImportFilter_getSupportedServiceNames();
1072 6 : }
1073 :
1074 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|