LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/cdr/src/lib - CDRContentCollector.cpp (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 697 0.0 %
Date: 2012-12-17 Functions: 0 40 0.0 %
Legend: Lines: hit not hit

          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: */

Generated by: LCOV version 1.10