Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* libcdr
3 : * Version: MPL 1.1 / GPLv2+ / LGPLv2+
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 or as specified alternatively below. You may obtain a copy of
8 : * the License at 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 : * Major Contributor(s):
16 : * Copyright (C) 2012 Fridrich Strba <fridrich.strba@bluewin.ch>
17 : *
18 : *
19 : * All Rights Reserved.
20 : *
21 : * For minor contributions see the git repository.
22 : *
23 : * Alternatively, the contents of this file may be used under the terms of
24 : * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
25 : * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
26 : * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
27 : * instead of those above.
28 : */
29 :
30 : #include <math.h>
31 : #include <string.h>
32 : #include "CDRSVGGenerator.h"
33 : #include "CDRContentCollector.h"
34 : #include "CDRInternalStream.h"
35 : #include "CMXDocument.h"
36 : #include "libcdr_utils.h"
37 :
38 : #ifndef M_PI
39 : #define M_PI 3.14159265358979323846
40 : #endif
41 :
42 : #ifndef DUMP_PATTERN
43 : #define DUMP_PATTERN 0
44 : #endif
45 :
46 : #ifndef DUMP_VECT
47 : #define DUMP_VECT 0
48 : #endif
49 :
50 0 : libcdr::CDRContentCollector::CDRContentCollector(libcdr::CDRParserState &ps, libwpg::WPGPaintInterface *painter) :
51 : m_painter(painter),
52 : m_isPageProperties(false), m_isPageStarted(false), m_ignorePage(false),
53 0 : m_page(ps.m_pages[0]), m_pageIndex(0), m_currentFildId(0.0), m_currentOutlId(0), m_spnd(0),
54 : m_currentObjectLevel(0), m_currentGroupLevel(0), m_currentVectLevel(0), m_currentPageLevel(0),
55 : m_currentImage(), m_currentText(), m_currentTextOffsetX(0.0), m_currentTextOffsetY(0.0),
56 : m_currentBBox(), m_currentPath(), m_currentTransforms(), m_fillTransforms(),
57 : m_polygon(0), m_isInPolygon(false), m_isInSpline(false), m_outputElements(0),
58 : m_contentOutputElements(), m_fillOutputElements(),
59 0 : m_groupLevels(), m_groupTransforms(), m_splineData(), m_fillOpacity(1.0), m_ps(ps)
60 : {
61 0 : m_outputElements = &m_contentOutputElements;
62 0 : }
63 :
64 0 : libcdr::CDRContentCollector::~CDRContentCollector()
65 : {
66 0 : if (m_isPageStarted)
67 0 : _endPage();
68 0 : }
69 :
70 0 : void libcdr::CDRContentCollector::_startPage(double width, double height)
71 : {
72 0 : if (m_ignorePage)
73 0 : return;
74 0 : WPXPropertyList propList;
75 0 : propList.insert("svg:width", width);
76 0 : propList.insert("svg:height", height);
77 0 : if (m_painter)
78 : {
79 0 : m_painter->startGraphics(propList);
80 0 : m_isPageStarted = true;
81 0 : }
82 : }
83 :
84 0 : void libcdr::CDRContentCollector::_endPage()
85 : {
86 0 : if (!m_isPageStarted)
87 0 : return;
88 0 : while (!m_contentOutputElements.empty())
89 : {
90 0 : m_contentOutputElements.top().draw(m_painter);
91 0 : m_contentOutputElements.pop();
92 : }
93 0 : if (m_painter)
94 0 : m_painter->endGraphics();
95 0 : m_isPageStarted = false;
96 : }
97 :
98 0 : void libcdr::CDRContentCollector::collectPage(unsigned level)
99 : {
100 0 : m_isPageProperties = true;
101 0 : m_ignorePage = false;
102 0 : m_currentPageLevel = level;
103 0 : m_page = m_ps.m_pages[m_pageIndex++];
104 :
105 0 : }
106 :
107 0 : void libcdr::CDRContentCollector::collectObject(unsigned level)
108 : {
109 0 : if (!m_isPageStarted && !m_currentVectLevel && !m_ignorePage)
110 0 : _startPage(m_page.width, m_page.height);
111 0 : m_currentObjectLevel = level;
112 0 : m_currentFildId = 0;
113 0 : m_currentOutlId = 0;
114 0 : m_currentBBox = CDRBBox();
115 0 : }
116 :
117 0 : void libcdr::CDRContentCollector::collectGroup(unsigned level)
118 : {
119 0 : if (!m_isPageStarted && !m_currentVectLevel && !m_ignorePage)
120 0 : _startPage(m_page.width, m_page.height);
121 0 : WPXPropertyList propList;
122 0 : CDROutputElementList outputElement;
123 : // Since the CDR objects are drawn in reverse order, reverse the logic of groups too
124 0 : outputElement.addEndGroup();
125 0 : m_outputElements->push(outputElement);
126 0 : m_groupLevels.push(level);
127 0 : m_groupTransforms.push(CDRTransforms());
128 0 : }
129 :
130 0 : void libcdr::CDRContentCollector::collectVect(unsigned level)
131 : {
132 0 : m_currentVectLevel = level;
133 0 : m_outputElements = &m_fillOutputElements;
134 0 : m_page.width = 0.0;
135 0 : m_page.height = 0.0;
136 0 : m_page.offsetX = 0.0;
137 0 : m_page.offsetY = 0.0;
138 0 : }
139 :
140 0 : void libcdr::CDRContentCollector::collectFlags(unsigned flags, bool considerFlags)
141 : {
142 0 : if (m_isPageProperties && !(flags & 0x00ff0000))
143 : {
144 0 : if (!m_isPageStarted)
145 0 : _startPage(m_page.width, m_page.height);
146 : }
147 0 : else if (m_isPageProperties && considerFlags)
148 0 : m_ignorePage = true;
149 0 : m_isPageProperties = false;
150 0 : }
151 :
152 0 : void libcdr::CDRContentCollector::collectOtherList()
153 : {
154 : // m_isPageProperties = false;
155 0 : }
156 :
157 0 : void libcdr::CDRContentCollector::collectCubicBezier(double x1, double y1, double x2, double y2, double x, double y)
158 : {
159 : CDR_DEBUG_MSG(("CDRContentCollector::collectCubicBezier(%f, %f, %f, %f, %f, %f)\n", x1, y1, x2, y2, x, y));
160 0 : m_currentPath.appendCubicBezierTo(x1, y1, x2, y2, x, y);
161 0 : }
162 :
163 0 : void libcdr::CDRContentCollector::collectQuadraticBezier(double x1, double y1, double x, double y)
164 : {
165 : CDR_DEBUG_MSG(("CDRContentCollector::collectQuadraticBezier(%f, %f, %f, %f)\n", x1, y1, x, y));
166 0 : m_currentPath.appendQuadraticBezierTo(x1, y1, x, y);
167 0 : }
168 :
169 0 : void libcdr::CDRContentCollector::collectMoveTo(double x, double y)
170 : {
171 : CDR_DEBUG_MSG(("CDRContentCollector::collectMoveTo(%f, %f)\n", x, y));
172 0 : m_currentPath.appendMoveTo(x,y);
173 0 : }
174 :
175 0 : void libcdr::CDRContentCollector::collectLineTo(double x, double y)
176 : {
177 : CDR_DEBUG_MSG(("CDRContentCollector::collectLineTo(%f, %f)\n", x, y));
178 0 : m_currentPath.appendLineTo(x, y);
179 0 : }
180 :
181 0 : void libcdr::CDRContentCollector::collectArcTo(double rx, double ry, bool largeArc, bool sweep, double x, double y)
182 : {
183 : CDR_DEBUG_MSG(("CDRContentCollector::collectArcTo(%f, %f)\n", x, y));
184 0 : m_currentPath.appendArcTo(rx, ry, 0.0, largeArc, sweep, x, y);
185 0 : }
186 :
187 0 : void libcdr::CDRContentCollector::collectClosePath()
188 : {
189 : CDR_DEBUG_MSG(("CDRContentCollector::collectClosePath\n"));
190 0 : m_currentPath.appendClosePath();
191 0 : }
192 :
193 0 : void libcdr::CDRContentCollector::_flushCurrentPath()
194 : {
195 : CDR_DEBUG_MSG(("CDRContentCollector::collectFlushPath\n"));
196 0 : CDROutputElementList outputElement;
197 0 : if (!m_currentPath.empty() || (!m_splineData.empty() && m_isInSpline))
198 : {
199 0 : if (m_polygon && m_isInPolygon)
200 0 : m_polygon->create(m_currentPath);
201 0 : if (m_polygon)
202 : {
203 0 : delete m_polygon;
204 0 : m_polygon = 0;
205 : }
206 0 : m_isInPolygon = false;
207 0 : if (!m_splineData.empty() && m_isInSpline)
208 0 : m_splineData.create(m_currentPath);
209 0 : m_splineData.clear();
210 0 : m_isInSpline = false;
211 0 : bool firstPoint = true;
212 0 : bool wasMove = false;
213 0 : double initialX = 0.0;
214 0 : double initialY = 0.0;
215 0 : double previousX = 0.0;
216 0 : double previousY = 0.0;
217 0 : double x = 0.0;
218 0 : double y = 0.0;
219 0 : WPXPropertyList style;
220 0 : WPXPropertyListVector gradient;
221 0 : _fillProperties(style, gradient);
222 0 : _lineProperties(style);
223 0 : outputElement.addStyle(style, gradient);
224 0 : m_currentPath.transform(m_currentTransforms);
225 0 : if (!m_groupTransforms.empty())
226 0 : m_currentPath.transform(m_groupTransforms.top());
227 0 : CDRTransform tmpTrafo(1.0, 0.0, -m_page.offsetX, 0.0, 1.0, -m_page.offsetY);
228 0 : m_currentPath.transform(tmpTrafo);
229 0 : tmpTrafo = CDRTransform(1.0, 0.0, 0.0, 0.0, -1.0, m_page.height);
230 0 : m_currentPath.transform(tmpTrafo);
231 :
232 0 : std::vector<WPXPropertyList> tmpPath;
233 :
234 0 : WPXPropertyListVector path;
235 0 : m_currentPath.writeOut(path);
236 :
237 0 : bool isPathClosed = m_currentPath.isClosed();
238 :
239 0 : WPXPropertyListVector::Iter i(path);
240 0 : for (i.rewind(); i.next();)
241 : {
242 0 : bool ignoreM = false;
243 0 : if (!i()["libwpg:path-action"])
244 0 : continue;
245 0 : if (i()["svg:x"] && i()["svg:y"])
246 : {
247 0 : x = i()["svg:x"]->getDouble();
248 0 : y = i()["svg:y"]->getDouble();
249 0 : if (firstPoint)
250 : {
251 0 : initialX = x;
252 0 : initialY = y;
253 0 : firstPoint = false;
254 0 : wasMove = true;
255 : }
256 0 : else if (i()["libwpg:path-action"]->getStr() == "M")
257 : {
258 : // This is needed for a good generation of path from polygon
259 0 : if (CDR_ALMOST_ZERO(previousX - x) && CDR_ALMOST_ZERO(previousY - y))
260 0 : ignoreM = true;
261 : else
262 : {
263 0 : if (!tmpPath.empty())
264 : {
265 0 : if (!wasMove)
266 : {
267 0 : if ((CDR_ALMOST_ZERO(initialX - previousX) && CDR_ALMOST_ZERO(initialY - previousY)) || isPathClosed)
268 : {
269 0 : WPXPropertyList node;
270 0 : node.insert("libwpg:path-action", "Z");
271 0 : tmpPath.push_back(node);
272 : }
273 : }
274 : else
275 : {
276 0 : tmpPath.pop_back();
277 : }
278 : }
279 : }
280 :
281 0 : if (!ignoreM)
282 : {
283 0 : initialX = x;
284 0 : initialY = y;
285 0 : wasMove = true;
286 : }
287 :
288 : }
289 : else
290 0 : wasMove = false;
291 :
292 0 : if (!ignoreM)
293 : {
294 0 : tmpPath.push_back(i());
295 0 : previousX = x;
296 0 : previousY = y;
297 : }
298 :
299 : }
300 : }
301 0 : if (!tmpPath.empty())
302 : {
303 0 : if (!wasMove)
304 : {
305 0 : if ((CDR_ALMOST_ZERO(initialX - previousX) && CDR_ALMOST_ZERO(initialY - previousY)) || isPathClosed)
306 : {
307 0 : WPXPropertyList closedPath;
308 0 : closedPath.insert("libwpg:path-action", "Z");
309 0 : tmpPath.push_back(closedPath);
310 : }
311 : }
312 : else
313 0 : tmpPath.pop_back();
314 : }
315 0 : if (!tmpPath.empty())
316 : {
317 0 : WPXPropertyListVector outputPath;
318 0 : for (std::vector<WPXPropertyList>::const_iterator iter = tmpPath.begin(); iter != tmpPath.end(); ++iter)
319 0 : outputPath.append(*iter);
320 :
321 0 : outputElement.addPath(outputPath);
322 :
323 : }
324 0 : m_currentPath.clear();
325 : }
326 :
327 0 : if (m_currentImage.getImage().size())
328 : {
329 0 : double cx = m_currentImage.getMiddleX();
330 0 : double cy = m_currentImage.getMiddleY();
331 0 : m_currentTransforms.applyToPoint(cx, cy);
332 0 : if (!m_groupTransforms.empty())
333 0 : m_groupTransforms.top().applyToPoint(cx, cy);
334 0 : CDRTransform tmpTrafo(1.0, 0.0, -m_page.offsetX, 0.0, 1.0, -m_page.offsetY);
335 0 : tmpTrafo.applyToPoint(cx, cy);
336 0 : tmpTrafo = CDRTransform(1.0, 0.0, 0.0, 0.0, -1.0, m_page.height);
337 0 : tmpTrafo.applyToPoint(cx, cy);
338 0 : bool flipX(m_currentTransforms.getFlipX());
339 0 : bool flipY(m_currentTransforms.getFlipY());
340 0 : double width = m_currentTransforms.getScaleX() * m_currentImage.getWidth();
341 0 : double height = m_currentTransforms.getScaleY() * m_currentImage.getHeight();
342 0 : double rotate = m_currentTransforms.getRotation();
343 :
344 0 : WPXPropertyList propList;
345 :
346 0 : propList.insert("svg:x", cx - width / 2.0);
347 0 : propList.insert("svg:width", width);
348 0 : propList.insert("svg:y", cy - height / 2.0);
349 0 : propList.insert("svg:height", height);
350 :
351 0 : if (flipX)
352 : {
353 0 : propList.insert("draw:mirror-horizontal", true);
354 0 : rotate = M_PI - rotate;
355 : }
356 0 : if (flipY)
357 : {
358 0 : propList.insert("draw:mirror-vertical", true);
359 0 : rotate *= -1.0;
360 : }
361 :
362 0 : while (rotate < 0.0)
363 0 : rotate += 2.0*M_PI;
364 0 : while (rotate > 2.0*M_PI)
365 0 : rotate -= 2.0*M_PI;
366 :
367 0 : if (rotate != 0.0)
368 0 : propList.insert("libwpg:rotate", rotate * 180 / M_PI, WPX_GENERIC);
369 :
370 0 : propList.insert("libwpg:mime-type", "image/bmp");
371 :
372 0 : outputElement.addGraphicObject(propList, m_currentImage.getImage());
373 : }
374 0 : if (m_currentText.m_text.len())
375 : {
376 0 : double currentTextOffsetX = 0.0;
377 0 : double currentTextOffsetY = 0.0;
378 0 : m_currentTransforms.applyToPoint(currentTextOffsetX, currentTextOffsetY);
379 0 : if (!m_groupTransforms.empty())
380 0 : m_groupTransforms.top().applyToPoint(currentTextOffsetX, currentTextOffsetY);
381 0 : WPXPropertyList textFrameProps;
382 0 : if (m_currentBBox.getWidth() > 0.0 && m_currentBBox.getHeight() > 0.0)
383 : {
384 0 : textFrameProps.insert("svg:width", m_currentBBox.getWidth() * 1.05);
385 0 : textFrameProps.insert("svg:height", m_currentBBox.getHeight());
386 0 : currentTextOffsetX = m_currentBBox.getMinX();
387 0 : currentTextOffsetY = m_currentBBox.getMinY();
388 : }
389 0 : CDRTransform tmpTrafo(1.0, 0.0, -m_page.offsetX, 0.0, 1.0, -m_page.offsetY);
390 0 : tmpTrafo.applyToPoint(currentTextOffsetX, currentTextOffsetY);
391 0 : tmpTrafo = CDRTransform(1.0, 0.0, 0.0, 0.0, -1.0, m_page.height);
392 0 : tmpTrafo.applyToPoint(currentTextOffsetX, currentTextOffsetY);
393 0 : textFrameProps.insert("svg:x", currentTextOffsetX);
394 0 : textFrameProps.insert("svg:y", currentTextOffsetY - m_currentBBox.getHeight());
395 0 : textFrameProps.insert("fo:padding-top", 0.0);
396 0 : textFrameProps.insert("fo:padding-bottom", 0.0);
397 0 : textFrameProps.insert("fo:padding-left", 0.0);
398 0 : textFrameProps.insert("fo:padding-right", 0.0);
399 0 : outputElement.addStartTextObject(textFrameProps, WPXPropertyListVector());
400 0 : outputElement.addStartTextLine(WPXPropertyList());
401 0 : WPXPropertyList spanProps;
402 0 : double fontSize = (double)cdr_round(144.0*m_currentText.m_charStyle.m_fontSize) / 2.0;
403 0 : spanProps.insert("fo:font-size", fontSize, WPX_POINT);
404 0 : std::map<unsigned, WPXString>::const_iterator iterFont = m_ps.m_fonts.find(m_currentText.m_charStyle.m_fontId);
405 0 : if (iterFont != m_ps.m_fonts.end())
406 0 : spanProps.insert("style:font-name", iterFont->second);
407 0 : outputElement.addStartTextSpan(spanProps);
408 0 : outputElement.addInsertText(m_currentText.m_text);
409 0 : outputElement.addEndTextSpan();
410 0 : outputElement.addEndTextLine();
411 0 : outputElement.addEndTextObject();
412 : }
413 0 : m_currentImage = libcdr::CDRImage();
414 0 : if (!outputElement.empty())
415 0 : m_outputElements->push(outputElement);
416 0 : m_currentTransforms.clear();
417 0 : m_fillTransforms = libcdr::CDRTransforms();
418 0 : m_fillOpacity = 1.0;
419 0 : m_currentText = CDRText();
420 0 : }
421 :
422 0 : void libcdr::CDRContentCollector::collectTransform(const CDRTransforms &transforms, bool considerGroupTransform)
423 : {
424 0 : if (m_currentObjectLevel)
425 0 : m_currentTransforms = transforms;
426 0 : else if (!m_groupLevels.empty() && considerGroupTransform)
427 0 : m_groupTransforms.top() = transforms;
428 0 : }
429 :
430 0 : void libcdr::CDRContentCollector::collectFillTransform(const CDRTransforms &fillTrafos)
431 : {
432 0 : m_fillTransforms = fillTrafos;
433 0 : }
434 :
435 0 : void libcdr::CDRContentCollector::collectLevel(unsigned level)
436 : {
437 0 : if (level <= m_currentObjectLevel)
438 : {
439 0 : _flushCurrentPath();
440 0 : m_currentObjectLevel = 0;
441 : }
442 0 : while (!m_groupLevels.empty() && level <= m_groupLevels.top())
443 : {
444 0 : WPXPropertyList propList;
445 0 : CDROutputElementList outputElement;
446 : // since the CDR objects are drawn in reverse order, reverse group marks too
447 0 : outputElement.addStartGroup(propList);
448 0 : m_outputElements->push(outputElement);
449 0 : m_groupLevels.pop();
450 0 : m_groupTransforms.pop();
451 0 : }
452 0 : if (m_currentVectLevel && m_spnd && m_groupLevels.empty() && !m_fillOutputElements.empty())
453 : {
454 0 : CDRStringVector svgOutput;
455 0 : CDRSVGGenerator generator(svgOutput);
456 0 : WPXPropertyList propList;
457 0 : propList.insert("svg:width", m_page.width);
458 0 : propList.insert("svg:height", m_page.height);
459 0 : generator.startGraphics(propList);
460 0 : while (!m_fillOutputElements.empty())
461 : {
462 0 : m_fillOutputElements.top().draw(&generator);
463 0 : m_fillOutputElements.pop();
464 : }
465 0 : generator.endGraphics();
466 0 : if (!svgOutput.empty())
467 : {
468 : const char *header =
469 0 : "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n";
470 0 : WPXBinaryData output((const unsigned char *)header, strlen(header));
471 0 : output.append((unsigned char *)svgOutput[0].cstr(), strlen(svgOutput[0].cstr()));
472 0 : m_ps.m_vects[m_spnd] = output;
473 : }
474 : #if DUMP_VECT
475 : WPXString filename;
476 : filename.sprintf("vect%.8x.svg", m_spnd);
477 : FILE *f = fopen(filename.cstr(), "wb");
478 : if (f)
479 : {
480 : const unsigned char *tmpBuffer = m_ps.m_vects[m_spnd].getDataBuffer();
481 : for (unsigned long k = 0; k < m_ps.m_vects[m_spnd].size(); k++)
482 : fprintf(f, "%c",tmpBuffer[k]);
483 : fclose(f);
484 : }
485 : #endif
486 0 : m_spnd = 0;
487 0 : m_page.width = 0.0;
488 0 : m_page.height = 0.0;
489 0 : m_page.offsetX = 0.0;
490 0 : m_page.offsetY = 0.0;
491 : }
492 0 : if (level <= m_currentVectLevel)
493 : {
494 0 : m_currentVectLevel = 0;
495 0 : m_outputElements = &m_contentOutputElements;
496 0 : m_page = m_ps.m_pages[m_pageIndex ? m_pageIndex-1 : 0];
497 : }
498 0 : if (level <= m_currentPageLevel)
499 : {
500 0 : _endPage();
501 0 : m_currentPageLevel = 0;
502 : }
503 0 : }
504 :
505 0 : void libcdr::CDRContentCollector::collectFildId(unsigned id)
506 : {
507 0 : m_currentFildId = id;
508 0 : }
509 :
510 0 : void libcdr::CDRContentCollector::collectOutlId(unsigned id)
511 : {
512 0 : m_currentOutlId = id;
513 0 : }
514 :
515 0 : void libcdr::CDRContentCollector::collectRotate(double angle, double cx, double cy)
516 : {
517 0 : CDRTransform trafo1(1.0, 0.0, -cx, 0.0, 1.0, -cy);
518 0 : m_currentPath.transform(trafo1);
519 0 : CDRTransform trafo2(cos(angle), -sin(angle), 0, sin(angle), cos(angle), 0);
520 0 : m_currentPath.transform(trafo2);
521 0 : CDRTransform trafo3(1.0, 0.0, cx, 0.0, 1.0, cy);
522 0 : m_currentPath.transform(trafo3);
523 0 : }
524 :
525 0 : void libcdr::CDRContentCollector::collectPolygon()
526 : {
527 0 : m_isInPolygon = true;
528 0 : }
529 :
530 0 : void libcdr::CDRContentCollector::collectSpline()
531 : {
532 0 : m_isInSpline = true;
533 0 : }
534 :
535 0 : void libcdr::CDRContentCollector::collectPolygonTransform(unsigned numAngles, unsigned nextPoint, double rx, double ry, double cx, double cy)
536 : {
537 0 : if (m_polygon)
538 0 : delete m_polygon;
539 0 : m_polygon = new CDRPolygon(numAngles, nextPoint, rx, ry, cx, cy);
540 0 : }
541 :
542 0 : void libcdr::CDRContentCollector::_fillProperties(WPXPropertyList &propList, WPXPropertyListVector &vec)
543 : {
544 0 : if (m_fillOpacity < 1.0)
545 0 : propList.insert("draw:opacity", m_fillOpacity, WPX_PERCENT);
546 0 : if (m_currentFildId == 0)
547 0 : propList.insert("draw:fill", "none");
548 : else
549 : {
550 0 : std::map<unsigned, CDRFillStyle>::iterator iter = m_ps.m_fillStyles.find(m_currentFildId);
551 0 : if (iter == m_ps.m_fillStyles.end())
552 0 : propList.insert("draw:fill", "none");
553 : else
554 : {
555 0 : switch (iter->second.fillType)
556 : {
557 : case 1: // Solid
558 0 : propList.insert("draw:fill", "solid");
559 0 : propList.insert("draw:fill-color", m_ps.getRGBColorString(iter->second.color1));
560 0 : propList.insert("svg:fill-rule", "evenodd");
561 0 : break;
562 : case 2: // Gradient
563 0 : if (iter->second.gradient.m_stops.empty())
564 0 : propList.insert("draw:fill", "none");
565 0 : else if (iter->second.gradient.m_stops.size() == 1)
566 : {
567 0 : propList.insert("draw:fill", "solid");
568 0 : propList.insert("draw:fill-color", m_ps.getRGBColorString(iter->second.gradient.m_stops[0].m_color));
569 0 : propList.insert("svg:fill-rule", "evenodd");
570 : }
571 0 : else if (iter->second.gradient.m_stops.size() == 2)
572 : {
573 0 : double angle = iter->second.gradient.m_angle;
574 0 : while (angle < 0.0)
575 0 : angle += 360.0;
576 0 : while (angle > 360.0)
577 0 : angle -= 360.0;
578 0 : propList.insert("draw:fill", "gradient");
579 0 : propList.insert("draw:start-color", m_ps.getRGBColorString(iter->second.gradient.m_stops[0].m_color));
580 0 : propList.insert("draw:end-color", m_ps.getRGBColorString(iter->second.gradient.m_stops[1].m_color));
581 0 : propList.insert("draw:angle", (int)angle);
582 0 : switch (iter->second.gradient.m_type)
583 : {
584 : case 1: // linear
585 : case 3: // conical
586 0 : propList.insert("draw:style", "linear");
587 0 : angle += 90.0;
588 0 : while (angle < 0.0)
589 0 : angle += 360.0;
590 0 : while (angle > 360.0)
591 0 : angle -= 360.0;
592 0 : propList.insert("draw:angle", (int)angle);
593 0 : propList.insert("draw:border", (double)(iter->second.gradient.m_edgeOffset)/100.0, WPX_PERCENT);
594 0 : break;
595 : case 2: // radial
596 0 : propList.insert("draw:border", (2.0 * (double)(iter->second.gradient.m_edgeOffset)/100.0), WPX_PERCENT);
597 0 : propList.insert("draw:style", "radial");
598 0 : propList.insert("svg:cx", (double)(0.5 + iter->second.gradient.m_centerXOffset/200.0), WPX_PERCENT);
599 0 : propList.insert("svg:cy", (double)(0.5 + iter->second.gradient.m_centerXOffset/200.0), WPX_PERCENT);
600 0 : break;
601 : case 4: // square
602 0 : propList.insert("draw:border", (2.0 * (double)(iter->second.gradient.m_edgeOffset)/100.0), WPX_PERCENT);
603 0 : propList.insert("draw:style", "square");
604 0 : propList.insert("svg:cx", (double)(0.5 + iter->second.gradient.m_centerXOffset/200.0), WPX_PERCENT);
605 0 : propList.insert("svg:cy", (double)(0.5 + iter->second.gradient.m_centerXOffset/200.0), WPX_PERCENT);
606 0 : break;
607 : default:
608 0 : propList.insert("draw:style", "linear");
609 0 : angle += 90.0;
610 0 : while (angle < 0.0)
611 0 : angle += 360.0;
612 0 : while (angle > 360.0)
613 0 : angle -= 360.0;
614 0 : propList.insert("draw:angle", (int)angle);
615 0 : for (unsigned i = 0; i < iter->second.gradient.m_stops.size(); i++)
616 : {
617 0 : libcdr::CDRGradientStop &gradStop = iter->second.gradient.m_stops[i];
618 0 : WPXPropertyList stopElement;
619 0 : stopElement.insert("svg:offset", gradStop.m_offset, WPX_PERCENT);
620 0 : stopElement.insert("svg:stop-color", m_ps.getRGBColorString(gradStop.m_color));
621 0 : stopElement.insert("svg:stop-opacity", m_fillOpacity, WPX_PERCENT);
622 0 : vec.append(stopElement);
623 0 : }
624 0 : break;
625 : }
626 : }
627 : else // output svg gradient as a hail mary pass towards ODG that does not really support it
628 : {
629 0 : propList.insert("draw:fill", "gradient");
630 0 : propList.insert("draw:style", "linear");
631 0 : double angle = iter->second.gradient.m_angle;
632 0 : angle += 90.0;
633 0 : while (angle < 0.0)
634 0 : angle += 360.0;
635 0 : while (angle > 360.0)
636 0 : angle -= 360.0;
637 0 : propList.insert("draw:angle", (int)angle);
638 0 : for (unsigned i = 0; i < iter->second.gradient.m_stops.size(); i++)
639 : {
640 0 : libcdr::CDRGradientStop &gradStop = iter->second.gradient.m_stops[i];
641 0 : WPXPropertyList stopElement;
642 0 : stopElement.insert("svg:offset", gradStop.m_offset, WPX_PERCENT);
643 0 : stopElement.insert("svg:stop-color", m_ps.getRGBColorString(gradStop.m_color));
644 0 : stopElement.insert("svg:stop-opacity", m_fillOpacity, WPX_PERCENT);
645 0 : vec.append(stopElement);
646 0 : }
647 : }
648 0 : break;
649 : case 7: // Pattern
650 : {
651 0 : std::map<unsigned, CDRPattern>::iterator iterPattern = m_ps.m_patterns.find(iter->second.imageFill.id);
652 0 : if (iterPattern != m_ps.m_patterns.end())
653 : {
654 0 : propList.insert("draw:fill", "bitmap");
655 0 : WPXBinaryData image;
656 0 : _generateBitmapFromPattern(image, iterPattern->second, iter->second.color1, iter->second.color2);
657 : #if DUMP_PATTERN
658 : WPXString filename;
659 : filename.sprintf("pattern%.8x.bmp", iter->second.imageFill.id);
660 : FILE *f = fopen(filename.cstr(), "wb");
661 : if (f)
662 : {
663 : const unsigned char *tmpBuffer = image.getDataBuffer();
664 : for (unsigned long k = 0; k < image.size(); k++)
665 : fprintf(f, "%c",tmpBuffer[k]);
666 : fclose(f);
667 : }
668 : #endif
669 0 : propList.insert("draw:fill-image", image.getBase64Data());
670 0 : propList.insert("libwpg:mime-type", "image/bmp");
671 0 : propList.insert("style:repeat", "repeat");
672 0 : if (iter->second.imageFill.isRelative)
673 : {
674 0 : propList.insert("svg:width", iter->second.imageFill.width, WPX_PERCENT);
675 0 : propList.insert("svg:height", iter->second.imageFill.height, WPX_PERCENT);
676 : }
677 : else
678 : {
679 0 : double scaleX = 1.0;
680 0 : double scaleY = 1.0;
681 0 : if (iter->second.imageFill.flags & 0x04) // scale fill with image
682 : {
683 0 : scaleX = m_currentTransforms.getScaleX();
684 0 : scaleY = m_currentTransforms.getScaleY();
685 : }
686 0 : propList.insert("svg:width", iter->second.imageFill.width * scaleX);
687 0 : propList.insert("svg:height", iter->second.imageFill.height * scaleY);
688 : }
689 0 : propList.insert("draw:fill-image-ref-point", "bottom-left");
690 0 : if (iter->second.imageFill.isRelative)
691 : {
692 0 : if (iter->second.imageFill.xOffset != 0.0 && iter->second.imageFill.xOffset != 1.0)
693 0 : propList.insert("draw:fill-image-ref-point-x", iter->second.imageFill.xOffset, WPX_PERCENT);
694 0 : if (iter->second.imageFill.yOffset != 0.0 && iter->second.imageFill.yOffset != 1.0)
695 0 : propList.insert("draw:fill-image-ref-point-y", iter->second.imageFill.yOffset, WPX_PERCENT);
696 : }
697 : else
698 : {
699 0 : if (m_fillTransforms.getTranslateX() != 0.0)
700 : {
701 0 : double xOffset = m_fillTransforms.getTranslateX() / iter->second.imageFill.width;
702 0 : while (xOffset < 0.0)
703 0 : xOffset += 1.0;
704 0 : while (xOffset > 1.0)
705 0 : xOffset -= 1.0;
706 0 : propList.insert("draw:fill-image-ref-point-x", xOffset, WPX_PERCENT);
707 : }
708 0 : if (m_fillTransforms.getTranslateY() != 0.0)
709 : {
710 0 : double yOffset = m_fillTransforms.getTranslateY() / iter->second.imageFill.width;
711 0 : while (yOffset < 0.0)
712 0 : yOffset += 1.0;
713 0 : while (yOffset > 1.0)
714 0 : yOffset -= 1.0;
715 0 : propList.insert("draw:fill-image-ref-point-y", 1.0 - yOffset, WPX_PERCENT);
716 : }
717 0 : }
718 : }
719 : else
720 : {
721 : // We did not find the pattern, so fill solid with the background colour
722 0 : propList.insert("draw:fill", "solid");
723 0 : propList.insert("draw:fill-color", m_ps.getRGBColorString(iter->second.color2));
724 0 : propList.insert("svg:fill-rule", "evenodd");
725 : }
726 : }
727 0 : break;
728 : case 9: // Bitmap
729 : case 11: // Texture
730 : {
731 0 : std::map<unsigned, WPXBinaryData>::iterator iterBmp = m_ps.m_bmps.find(iter->second.imageFill.id);
732 0 : if (iterBmp != m_ps.m_bmps.end())
733 : {
734 0 : propList.insert("libwpg:mime-type", "image/bmp");
735 0 : propList.insert("draw:fill", "bitmap");
736 0 : propList.insert("draw:fill-image", iterBmp->second.getBase64Data());
737 0 : propList.insert("style:repeat", "repeat");
738 0 : if (iter->second.imageFill.isRelative)
739 : {
740 0 : propList.insert("svg:width", iter->second.imageFill.width, WPX_PERCENT);
741 0 : propList.insert("svg:height", iter->second.imageFill.height, WPX_PERCENT);
742 : }
743 : else
744 : {
745 0 : double scaleX = 1.0;
746 0 : double scaleY = 1.0;
747 0 : if (iter->second.imageFill.flags & 0x04) // scale fill with image
748 : {
749 0 : scaleX = m_currentTransforms.getScaleX();
750 0 : scaleY = m_currentTransforms.getScaleY();
751 : }
752 0 : propList.insert("svg:width", iter->second.imageFill.width * scaleX);
753 0 : propList.insert("svg:height", iter->second.imageFill.height * scaleY);
754 : }
755 0 : propList.insert("draw:fill-image-ref-point", "bottom-left");
756 0 : if (iter->second.imageFill.isRelative)
757 : {
758 0 : if (iter->second.imageFill.xOffset != 0.0 && iter->second.imageFill.xOffset != 1.0)
759 0 : propList.insert("draw:fill-image-ref-point-x", iter->second.imageFill.xOffset, WPX_PERCENT);
760 0 : if (iter->second.imageFill.yOffset != 0.0 && iter->second.imageFill.yOffset != 1.0)
761 0 : propList.insert("draw:fill-image-ref-point-y", iter->second.imageFill.yOffset, WPX_PERCENT);
762 : }
763 : else
764 : {
765 0 : if (m_fillTransforms.getTranslateX() != 0.0)
766 : {
767 0 : double xOffset = m_fillTransforms.getTranslateX() / iter->second.imageFill.width;
768 0 : while (xOffset < 0.0)
769 0 : xOffset += 1.0;
770 0 : while (xOffset > 1.0)
771 0 : xOffset -= 1.0;
772 0 : propList.insert("draw:fill-image-ref-point-x", xOffset, WPX_PERCENT);
773 : }
774 0 : if (m_fillTransforms.getTranslateY() != 0.0)
775 : {
776 0 : double yOffset = m_fillTransforms.getTranslateY() / iter->second.imageFill.width;
777 0 : while (yOffset < 0.0)
778 0 : yOffset += 1.0;
779 0 : while (yOffset > 1.0)
780 0 : yOffset -= 1.0;
781 0 : propList.insert("draw:fill-image-ref-point-y", 1.0 - yOffset, WPX_PERCENT);
782 : }
783 : }
784 : }
785 : else
786 0 : propList.insert("draw:fill", "none");
787 : }
788 0 : break;
789 : case 10: // Full color
790 : {
791 0 : std::map<unsigned, WPXBinaryData>::iterator iterVect = m_ps.m_vects.find(iter->second.imageFill.id);
792 0 : if (iterVect != m_ps.m_vects.end())
793 : {
794 0 : propList.insert("draw:fill", "bitmap");
795 0 : propList.insert("libwpg:mime-type", "image/svg+xml");
796 0 : propList.insert("draw:fill-image", iterVect->second.getBase64Data());
797 0 : propList.insert("style:repeat", "repeat");
798 0 : if (iter->second.imageFill.isRelative)
799 : {
800 0 : propList.insert("svg:width", iter->second.imageFill.width, WPX_PERCENT);
801 0 : propList.insert("svg:height", iter->second.imageFill.height, WPX_PERCENT);
802 : }
803 : else
804 : {
805 0 : double scaleX = 1.0;
806 0 : double scaleY = 1.0;
807 0 : if (iter->second.imageFill.flags & 0x04) // scale fill with image
808 : {
809 0 : scaleX = m_currentTransforms.getScaleX();
810 0 : scaleY = m_currentTransforms.getScaleY();
811 : }
812 0 : propList.insert("svg:width", iter->second.imageFill.width * scaleX);
813 0 : propList.insert("svg:height", iter->second.imageFill.height * scaleY);
814 : }
815 0 : propList.insert("draw:fill-image-ref-point", "bottom-left");
816 0 : if (iter->second.imageFill.isRelative)
817 : {
818 0 : if (iter->second.imageFill.xOffset != 0.0 && iter->second.imageFill.xOffset != 1.0)
819 0 : propList.insert("draw:fill-image-ref-point-x", iter->second.imageFill.xOffset, WPX_PERCENT);
820 0 : if (iter->second.imageFill.yOffset != 0.0 && iter->second.imageFill.yOffset != 1.0)
821 0 : propList.insert("draw:fill-image-ref-point-y", iter->second.imageFill.yOffset, WPX_PERCENT);
822 : }
823 : else
824 : {
825 0 : if (m_fillTransforms.getTranslateX() != 0.0)
826 : {
827 0 : double xOffset = m_fillTransforms.getTranslateX() / iter->second.imageFill.width;
828 0 : while (xOffset < 0.0)
829 0 : xOffset += 1.0;
830 0 : while (xOffset > 1.0)
831 0 : xOffset -= 1.0;
832 0 : propList.insert("draw:fill-image-ref-point-x", xOffset, WPX_PERCENT);
833 : }
834 0 : if (m_fillTransforms.getTranslateY() != 0.0)
835 : {
836 0 : double yOffset = m_fillTransforms.getTranslateY() / iter->second.imageFill.width;
837 0 : while (yOffset < 0.0)
838 0 : yOffset += 1.0;
839 0 : while (yOffset > 1.0)
840 0 : yOffset -= 1.0;
841 0 : propList.insert("draw:fill-image-ref-point-y", 1.0 - yOffset, WPX_PERCENT);
842 : }
843 : }
844 : }
845 : else
846 0 : propList.insert("draw:fill", "none");
847 : }
848 0 : break;
849 : default:
850 0 : propList.insert("draw:fill", "none");
851 0 : break;
852 : }
853 : }
854 : }
855 0 : }
856 :
857 0 : void libcdr::CDRContentCollector::_lineProperties(WPXPropertyList &propList)
858 : {
859 0 : if (m_currentOutlId == 0)
860 : {
861 0 : propList.insert("draw:stroke", "solid");
862 0 : propList.insert("svg:stroke-width", 0.0);
863 0 : propList.insert("svg:stroke-color", "#000000");
864 : }
865 : else
866 : {
867 0 : std::map<unsigned, CDRLineStyle>::iterator iter = m_ps.m_lineStyles.find(m_currentOutlId);
868 0 : if (iter == m_ps.m_lineStyles.end())
869 : {
870 0 : propList.insert("draw:stroke", "solid");
871 0 : propList.insert("svg:stroke-width", 0.0);
872 0 : propList.insert("svg:stroke-color", "#000000");
873 : }
874 0 : else if (iter->second.lineType & 0x1)
875 0 : propList.insert("draw:stroke", "none");
876 0 : else if (iter->second.lineType & 0x6)
877 : {
878 0 : if (iter->second.dashArray.size() && (iter->second.lineType & 0x4))
879 0 : propList.insert("draw:stroke", "dash");
880 : else
881 0 : propList.insert("draw:stroke", "solid");
882 0 : double scale = 1.0;
883 0 : if (iter->second.lineType & 0x20) // scale line with image
884 : {
885 0 : scale = m_currentTransforms.getScaleX();
886 0 : double scaleY = m_currentTransforms.getScaleY();
887 0 : if (scaleY > scale)
888 0 : scale = scaleY;
889 : }
890 0 : scale *= iter->second.stretch;
891 0 : propList.insert("svg:stroke-width", iter->second.lineWidth * scale);
892 0 : propList.insert("svg:stroke-color", m_ps.getRGBColorString(iter->second.color));
893 :
894 0 : switch (iter->second.capsType)
895 : {
896 : case 1:
897 0 : propList.insert("svg:stroke-linecap", "round");
898 0 : break;
899 : case 2:
900 0 : propList.insert("svg:stroke-linecap", "square");
901 0 : break;
902 : default:
903 0 : propList.insert("svg:stroke-linecap", "butt");
904 : }
905 :
906 0 : switch (iter->second.joinType)
907 : {
908 : case 1:
909 0 : propList.insert("svg:stroke-linejoin", "round");
910 0 : break;
911 : case 2:
912 0 : propList.insert("svg:stroke-linejoin", "bevel");
913 0 : break;
914 : default:
915 0 : propList.insert("svg:stroke-linejoin", "miter");
916 : }
917 :
918 0 : if (iter->second.dashArray.size())
919 : {
920 0 : int dots1 = 0;
921 0 : int dots2 = 0;
922 0 : unsigned dots1len = 0;
923 0 : unsigned dots2len = 0;
924 0 : unsigned gap = 0;
925 :
926 0 : if (iter->second.dashArray.size() >= 2)
927 : {
928 0 : dots1len = iter->second.dashArray[0];
929 0 : gap = iter->second.dashArray[1];
930 : }
931 :
932 0 : unsigned count = iter->second.dashArray.size() / 2;
933 0 : unsigned i = 0;
934 0 : for (; i < count;)
935 : {
936 0 : if (dots1len == iter->second.dashArray[2*i])
937 0 : dots1++;
938 : else
939 0 : break;
940 0 : gap = gap < iter->second.dashArray[2*i+1] ? iter->second.dashArray[2*i+1] : gap;
941 0 : i++;
942 : }
943 0 : if (i < count)
944 : {
945 0 : dots2len = iter->second.dashArray[2*i];
946 0 : gap = gap < iter->second.dashArray[2*i+1] ? iter->second.dashArray[2*i+1] : gap;
947 : }
948 0 : for (; i < count;)
949 : {
950 0 : if (dots2len == iter->second.dashArray[2*i])
951 0 : dots2++;
952 : else
953 0 : break;
954 0 : gap = gap < iter->second.dashArray[2*i+1] ? iter->second.dashArray[2*i+1] : gap;
955 0 : i++;
956 : }
957 0 : if (!dots2)
958 : {
959 0 : dots2 = dots1;
960 0 : dots2len = dots1len;
961 : }
962 0 : propList.insert("draw:dots1", dots1);
963 0 : propList.insert("draw:dots1-length", 72.0*(iter->second.lineWidth * scale)*dots1len, WPX_POINT);
964 0 : propList.insert("draw:dots2", dots2);
965 0 : propList.insert("draw:dots2-length", 72.0*(iter->second.lineWidth * scale)*dots2len, WPX_POINT);
966 0 : propList.insert("draw:distance", 72.0*(iter->second.lineWidth * scale)*gap, WPX_POINT);
967 : }
968 : }
969 : else
970 : {
971 0 : propList.insert("draw:stroke", "solid");
972 0 : propList.insert("svg:stroke-width", 0.0);
973 0 : propList.insert("svg:stroke-color", "#000000");
974 : }
975 :
976 : }
977 0 : }
978 :
979 0 : void libcdr::CDRContentCollector::_generateBitmapFromPattern(WPXBinaryData &bitmap, const CDRPattern &pattern, const CDRColor &fgColor, const CDRColor &bgColor)
980 : {
981 0 : unsigned height = pattern.height;
982 0 : unsigned width = pattern.width;
983 0 : unsigned tmpPixelSize = (unsigned)(height * width);
984 0 : if (tmpPixelSize < (unsigned)height) // overflow
985 0 : return;
986 :
987 0 : unsigned tmpDIBImageSize = tmpPixelSize * 4;
988 0 : if (tmpPixelSize > tmpDIBImageSize) // overflow !!!
989 0 : return;
990 :
991 0 : unsigned tmpDIBOffsetBits = 14 + 40;
992 0 : unsigned tmpDIBFileSize = tmpDIBOffsetBits + tmpDIBImageSize;
993 0 : if (tmpDIBImageSize > tmpDIBFileSize) // overflow !!!
994 0 : return;
995 :
996 : // Create DIB file header
997 0 : writeU16(bitmap, 0x4D42); // Type
998 0 : writeU32(bitmap, tmpDIBFileSize); // Size
999 0 : writeU16(bitmap, 0); // Reserved1
1000 0 : writeU16(bitmap, 0); // Reserved2
1001 0 : writeU32(bitmap, tmpDIBOffsetBits); // OffsetBits
1002 :
1003 : // Create DIB Info header
1004 0 : writeU32(bitmap, 40); // Size
1005 :
1006 0 : writeU32(bitmap, width); // Width
1007 0 : writeU32(bitmap, height); // Height
1008 :
1009 0 : writeU16(bitmap, 1); // Planes
1010 0 : writeU16(bitmap, 32); // BitCount
1011 0 : writeU32(bitmap, 0); // Compression
1012 0 : writeU32(bitmap, tmpDIBImageSize); // SizeImage
1013 0 : writeU32(bitmap, 0); // XPelsPerMeter
1014 0 : writeU32(bitmap, 0); // YPelsPerMeter
1015 0 : writeU32(bitmap, 0); // ColorsUsed
1016 0 : writeU32(bitmap, 0); // ColorsImportant
1017 :
1018 : // The Bitmaps in CDR are padded to 32bit border
1019 0 : unsigned lineWidth = (width + 7) / 8;
1020 :
1021 0 : unsigned foreground = m_ps._getRGBColor(fgColor);
1022 0 : unsigned background = m_ps._getRGBColor(bgColor);
1023 :
1024 0 : for (unsigned j = height; j > 0; --j)
1025 : {
1026 0 : unsigned i = 0;
1027 0 : unsigned k = 0;
1028 0 : while (i <lineWidth && k < width)
1029 : {
1030 0 : unsigned l = 0;
1031 0 : unsigned char c = pattern.pattern[(j-1)*lineWidth+i];
1032 0 : i++;
1033 0 : while (k < width && l < 8)
1034 : {
1035 0 : if (c & 0x80)
1036 0 : writeU32(bitmap, background);
1037 : else
1038 0 : writeU32(bitmap, foreground);
1039 0 : c <<= 1;
1040 0 : l++;
1041 0 : k++;
1042 : }
1043 : }
1044 : }
1045 : }
1046 :
1047 0 : void libcdr::CDRContentCollector::collectBitmap(unsigned imageId, double x1, double x2, double y1, double y2)
1048 : {
1049 0 : std::map<unsigned, WPXBinaryData>::iterator iter = m_ps.m_bmps.find(imageId);
1050 0 : if (iter != m_ps.m_bmps.end())
1051 0 : m_currentImage = CDRImage(iter->second, x1, x2, y1, y2);
1052 0 : }
1053 :
1054 0 : void libcdr::CDRContentCollector::collectPpdt(const std::vector<std::pair<double, double> > &points, const std::vector<unsigned> &knotVector)
1055 : {
1056 0 : m_splineData = CDRSplineData(points, knotVector);
1057 0 : }
1058 :
1059 0 : void libcdr::CDRContentCollector::collectFillOpacity(double opacity)
1060 : {
1061 0 : m_fillOpacity = opacity;
1062 0 : }
1063 :
1064 0 : void libcdr::CDRContentCollector::collectBBox(double x0, double y0, double x1, double y1)
1065 : {
1066 0 : CDRBBox bBox(x0, y0, x1, y1);
1067 0 : if (m_currentVectLevel && m_page.width == 0.0 && m_page.height == 0.0)
1068 : {
1069 0 : m_page.width = bBox.getWidth();
1070 0 : m_page.height = bBox.getHeight();
1071 0 : m_page.offsetX = bBox.getMinX();
1072 0 : m_page.offsetY = bBox.getMinY();
1073 : }
1074 0 : m_currentBBox = bBox;
1075 0 : }
1076 :
1077 0 : void libcdr::CDRContentCollector::collectSpnd(unsigned spnd)
1078 : {
1079 0 : if (m_currentVectLevel && !m_spnd)
1080 0 : m_spnd = spnd;
1081 0 : else if (!m_currentVectLevel)
1082 0 : m_spnd = spnd;
1083 0 : }
1084 :
1085 0 : void libcdr::CDRContentCollector::collectVectorPattern(unsigned id, const WPXBinaryData &data)
1086 : {
1087 0 : WPXInputStream *input = const_cast<WPXInputStream *>(data.getDataStream());
1088 0 : input->seek(0, WPX_SEEK_SET);
1089 0 : if (!libcdr::CMXDocument::isSupported(input))
1090 : return;
1091 0 : CDRStringVector svgOutput;
1092 0 : input->seek(0, WPX_SEEK_SET);
1093 0 : if (!libcdr::CMXDocument::generateSVG(input, svgOutput))
1094 : return;
1095 0 : if (!svgOutput.empty())
1096 : {
1097 : const char *header =
1098 0 : "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n";
1099 0 : WPXBinaryData output((const unsigned char *)header, strlen(header));
1100 0 : output.append((unsigned char *)svgOutput[0].cstr(), strlen(svgOutput[0].cstr()));
1101 0 : m_ps.m_vects[id] = output;
1102 0 : }
1103 : #if DUMP_VECT
1104 : WPXString filename;
1105 : filename.sprintf("vect%.8x.svg", id);
1106 : FILE *f = fopen(filename.cstr(), "wb");
1107 : if (f)
1108 : {
1109 : const unsigned char *tmpBuffer = m_ps.m_vects[id].getDataBuffer();
1110 : for (unsigned long k = 0; k < m_ps.m_vects[id].size(); k++)
1111 : fprintf(f, "%c",tmpBuffer[k]);
1112 : fclose(f);
1113 : }
1114 : #endif
1115 : }
1116 :
1117 0 : void libcdr::CDRContentCollector::collectArtisticText()
1118 : {
1119 0 : std::map<unsigned, CDRText>::const_iterator iter = m_ps.m_texts.find(m_spnd);
1120 0 : if (iter != m_ps.m_texts.end())
1121 0 : m_currentText = iter->second;
1122 0 : }
1123 :
1124 0 : void libcdr::CDRContentCollector::collectParagraphText()
1125 : {
1126 0 : std::map<unsigned, CDRText>::const_iterator iter = m_ps.m_texts.find(m_spnd);
1127 0 : if (iter != m_ps.m_texts.end())
1128 0 : m_currentText = iter->second;
1129 0 : }
1130 :
1131 : /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
|