LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/cdr/src/lib - CDRSVGGenerator.cpp (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 397 0.0 %
Date: 2012-12-17 Functions: 0 25 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) 2011 Fridrich Strba <fridrich.strba@bluewin.ch>
      17             :  * Copyright (C) 2011 Eilidh McAdam <tibbylickle@gmail.com>
      18             :  *
      19             :  *
      20             :  * All Rights Reserved.
      21             :  *
      22             :  * For minor contributions see the git repository.
      23             :  *
      24             :  * Alternatively, the contents of this file may be used under the terms of
      25             :  * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
      26             :  * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
      27             :  * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
      28             :  * instead of those above.
      29             :  */
      30             : 
      31             : #include "CDRSVGGenerator.h"
      32             : #include "libcdr.h"
      33             : #include <locale.h>
      34             : #include <sstream>
      35             : #include <string>
      36             : 
      37           0 : static std::string doubleToString(const double value)
      38             : {
      39           0 :   std::ostringstream tempStream;
      40           0 :   tempStream << value;
      41             : #ifndef __ANDROID__
      42           0 :   std::string decimalPoint(localeconv()->decimal_point);
      43             : #else
      44             :   std::string decimalPoint(".");
      45             : #endif
      46           0 :   if ((decimalPoint.size() == 0) || (decimalPoint == "."))
      47           0 :     return tempStream.str();
      48           0 :   std::string stringValue(tempStream.str());
      49           0 :   if (!stringValue.empty())
      50             :   {
      51             :     std::string::size_type pos;
      52           0 :     while ((pos = stringValue.find(decimalPoint)) != std::string::npos)
      53           0 :       stringValue.replace(pos,decimalPoint.size(),".");
      54             :   }
      55           0 :   return stringValue;
      56             : }
      57             : 
      58           0 : static unsigned stringToColour(const ::WPXString &s)
      59             : {
      60           0 :   std::string str(s.cstr());
      61           0 :   if (str[0] == '#')
      62             :   {
      63           0 :     if (str.length() != 7)
      64           0 :       return 0;
      65             :     else
      66           0 :       str.erase(str.begin());
      67             :   }
      68             :   else
      69           0 :     return 0;
      70             : 
      71           0 :   std::istringstream istr(str);
      72           0 :   unsigned val = 0;
      73           0 :   istr >> std::hex >> val;
      74           0 :   return val;
      75             : }
      76             : 
      77           0 : libcdr::CDRSVGGenerator::CDRSVGGenerator(libcdr::CDRStringVector &vec): m_gradient(), m_style(), m_gradientIndex(1), m_patternIndex(1), m_shadowIndex(1), m_outputSink(), m_vec(vec)
      78             : {
      79           0 : }
      80             : 
      81           0 : libcdr::CDRSVGGenerator::~CDRSVGGenerator()
      82             : {
      83           0 : }
      84             : 
      85           0 : void libcdr::CDRSVGGenerator::startGraphics(const WPXPropertyList &propList)
      86             : {
      87           0 :   m_outputSink << "<svg:svg version=\"1.1\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" ";
      88           0 :   if (propList["svg:width"])
      89           0 :     m_outputSink << "width=\"" << doubleToString(72*(propList["svg:width"]->getDouble())) << "\" ";
      90           0 :   if (propList["svg:height"])
      91           0 :     m_outputSink << "height=\"" << doubleToString(72*(propList["svg:height"]->getDouble())) << "\"";
      92           0 :   m_outputSink << " >\n";
      93           0 : }
      94             : 
      95           0 : void libcdr::CDRSVGGenerator::endGraphics()
      96             : {
      97           0 :   m_outputSink << "</svg:svg>\n";
      98           0 :   m_vec.append(m_outputSink.str().c_str());
      99           0 :   m_outputSink.str("");
     100           0 : }
     101             : 
     102           0 : void libcdr::CDRSVGGenerator::setStyle(const ::WPXPropertyList &propList, const ::WPXPropertyListVector &gradient)
     103             : {
     104           0 :   m_style.clear();
     105           0 :   m_style = propList;
     106             : 
     107           0 :   m_gradient = gradient;
     108           0 :   if(m_style["draw:shadow"] && m_style["draw:shadow"]->getStr() == "visible")
     109             :   {
     110           0 :     double shadowRed = 0.0;
     111           0 :     double shadowGreen = 0.0;
     112           0 :     double shadowBlue = 0.0;
     113           0 :     if (m_style["draw:shadow-color"])
     114             :     {
     115           0 :       unsigned shadowColour = stringToColour(m_style["draw:shadow-color"]->getStr());
     116           0 :       shadowRed = (double)((shadowColour & 0x00ff0000) >> 16)/255.0;
     117           0 :       shadowGreen = (double)((shadowColour & 0x0000ff00) >> 8)/255.0;
     118           0 :       shadowBlue = (double)(shadowColour & 0x000000ff)/255.0;
     119             :     }
     120           0 :     m_outputSink << "<svg:defs>\n";
     121           0 :     m_outputSink << "<svg:filter filterUnits=\"userSpaceOnUse\" id=\"shadow" << m_shadowIndex++ << "\">";
     122           0 :     m_outputSink << "<svg:feOffset in=\"SourceGraphic\" result=\"offset\" ";
     123           0 :     m_outputSink << "dx=\"" << doubleToString(72*m_style["draw:shadow-offset-x"]->getDouble()) << "\" ";
     124           0 :     m_outputSink << "dy=\"" << doubleToString(72*m_style["draw:shadow-offset-y"]->getDouble()) << "\"/>";
     125           0 :     m_outputSink << "<svg:feColorMatrix in=\"offset\" result=\"offset-color\" type=\"matrix\" values=\"";
     126           0 :     m_outputSink << "0 0 0 0 " << doubleToString(shadowRed) ;
     127           0 :     m_outputSink << " 0 0 0 0 " << doubleToString(shadowGreen);
     128           0 :     m_outputSink << " 0 0 0 0 " << doubleToString(shadowBlue);
     129           0 :     if(m_style["draw:opacity"] && m_style["draw:opacity"]->getDouble() < 1)
     130           0 :       m_outputSink << " 0 0 0 "   << doubleToString(m_style["draw:shadow-opacity"]->getDouble()/m_style["draw:opacity"]->getDouble()) << " 0\"/>";
     131             :     else
     132           0 :       m_outputSink << " 0 0 0 "   << doubleToString(m_style["draw:shadow-opacity"]->getDouble()) << " 0\"/>";
     133           0 :     m_outputSink << "<svg:feMerge><svg:feMergeNode in=\"offset-color\" /><svg:feMergeNode in=\"SourceGraphic\" /></svg:feMerge></svg:filter></svg:defs>";
     134             :   }
     135             : 
     136           0 :   if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "gradient")
     137             :   {
     138           0 :     double angle = (m_style["draw:angle"] ? m_style["draw:angle"]->getDouble() : 0.0);
     139           0 :     angle *= -1.0;
     140           0 :     while(angle < 0)
     141           0 :       angle += 360;
     142           0 :     while(angle > 360)
     143           0 :       angle -= 360;
     144             : 
     145           0 :     if (!m_gradient.count())
     146             :     {
     147           0 :       if (m_style["draw:style"] &&
     148           0 :           (m_style["draw:style"]->getStr() == "radial" ||
     149           0 :            m_style["draw:style"]->getStr() == "rectangular" ||
     150           0 :            m_style["draw:style"]->getStr() == "square" ||
     151           0 :            m_style["draw:style"]->getStr() == "ellipsoid"))
     152             :       {
     153           0 :         m_outputSink << "<svg:defs>\n";
     154           0 :         m_outputSink << "  <svg:radialGradient id=\"grad" << m_gradientIndex++ << "\"";
     155             : 
     156           0 :         if (m_style["svg:cx"])
     157           0 :           m_outputSink << " cx=\"" << m_style["svg:cx"]->getStr().cstr() << "\"";
     158           0 :         else if (m_style["draw:cx"])
     159           0 :           m_outputSink << " cx=\"" << m_style["draw:cx"]->getStr().cstr() << "\"";
     160             : 
     161           0 :         if (m_style["svg:cy"])
     162           0 :           m_outputSink << " cy=\"" << m_style["svg:cy"]->getStr().cstr() << "\"";
     163           0 :         else if (m_style["draw:cy"])
     164           0 :           m_outputSink << " cy=\"" << m_style["draw:cy"]->getStr().cstr() << "\"";
     165           0 :         m_outputSink << " r=\"" << (1 - (m_style["draw:border"] ? m_style["draw:border"]->getDouble() : 0))*100.0 << "%\" >\n";
     166           0 :         m_outputSink << " >\n";
     167             : 
     168           0 :         if (m_style["draw:start-color"] && m_style["draw:end-color"])
     169             :         {
     170           0 :           m_outputSink << "    <svg:stop offset=\"0%\"";
     171           0 :           m_outputSink << " stop-color=\"" << m_style["draw:end-color"]->getStr().cstr() << "\"";
     172           0 :           m_outputSink << " stop-opacity=\"" << (m_style["libwpg:end-opacity"] ? m_style["libwpg:end-opacity"]->getDouble() : 1) << "\" />" << std::endl;
     173             : 
     174           0 :           m_outputSink << "    <svg:stop offset=\"100%\"";
     175           0 :           m_outputSink << " stop-color=\"" << m_style["draw:start-color"]->getStr().cstr() << "\"";
     176           0 :           m_outputSink << " stop-opacity=\"" << (m_style["libwpg:start-opacity"] ? m_style["libwpg:start-opacity"]->getDouble() : 1) << "\" />" << std::endl;
     177             :         }
     178           0 :         m_outputSink << "  </svg:radialGradient>\n";
     179           0 :         m_outputSink << "</svg:defs>\n";
     180             :       }
     181           0 :       else if (m_style["draw:style"] && m_style["draw:style"]->getStr() == "linear")
     182             :       {
     183           0 :         m_outputSink << "<svg:defs>\n";
     184           0 :         m_outputSink << "  <svg:linearGradient id=\"grad" << m_gradientIndex++ << "\" >\n";
     185             : 
     186           0 :         if (m_style["draw:start-color"] && m_style["draw:end-color"])
     187             :         {
     188           0 :           m_outputSink << "    <svg:stop offset=\"0%\"";
     189           0 :           m_outputSink << " stop-color=\"" << m_style["draw:start-color"]->getStr().cstr() << "\"";
     190           0 :           m_outputSink << " stop-opacity=\"" << (m_style["libwpg:start-opacity"] ? m_style["libwpg:start-opacity"]->getDouble() : 1) << "\" />" << std::endl;
     191             : 
     192           0 :           m_outputSink << "    <svg:stop offset=\"100%\"";
     193           0 :           m_outputSink << " stop-color=\"" << m_style["draw:end-color"]->getStr().cstr() << "\"";
     194           0 :           m_outputSink << " stop-opacity=\"" << (m_style["libwpg:end-opacity"] ? m_style["libwpg:end-opacity"]->getDouble() : 1) << "\" />" << std::endl;
     195             :         }
     196           0 :         m_outputSink << "  </svg:linearGradient>\n";
     197             : 
     198             :         // not a simple horizontal gradient
     199           0 :         if(angle != 270)
     200             :         {
     201           0 :           m_outputSink << "  <svg:linearGradient xlink:href=\"#grad" << m_gradientIndex-1 << "\"";
     202           0 :           m_outputSink << " id=\"grad" << m_gradientIndex++ << "\" ";
     203           0 :           m_outputSink << "x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\" ";
     204           0 :           m_outputSink << "gradientTransform=\"rotate(" << angle << " .5 .5)\" ";
     205           0 :           m_outputSink << "gradientUnits=\"objectBoundingBox\" >\n";
     206           0 :           m_outputSink << "  </svg:linearGradient>\n";
     207             :         }
     208             : 
     209           0 :         m_outputSink << "</svg:defs>\n";
     210             :       }
     211           0 :       else if (m_style["draw:style"] && m_style["draw:style"]->getStr() == "axial")
     212             :       {
     213           0 :         m_outputSink << "<svg:defs>\n";
     214           0 :         m_outputSink << "  <svg:linearGradient id=\"grad" << m_gradientIndex++ << "\" >\n";
     215             : 
     216           0 :         if (m_style["draw:start-color"] && m_style["draw:end-color"])
     217             :         {
     218           0 :           m_outputSink << "    <svg:stop offset=\"0%\"";
     219           0 :           m_outputSink << " stop-color=\"" << m_style["draw:end-color"]->getStr().cstr() << "\"";
     220           0 :           m_outputSink << " stop-opacity=\"" << (m_style["libwpg:end-opacity"] ? m_style["libwpg:end-opacity"]->getDouble() : 1) << "\" />" << std::endl;
     221             : 
     222           0 :           m_outputSink << "    <svg:stop offset=\"50%\"";
     223           0 :           m_outputSink << " stop-color=\"" << m_style["draw:start-color"]->getStr().cstr() << "\"";
     224           0 :           m_outputSink << " stop-opacity=\"" << (m_style["libwpg:start-opacity"] ? m_style["libwpg:start-opacity"]->getDouble() : 1) << "\" />" << std::endl;
     225             : 
     226           0 :           m_outputSink << "    <svg:stop offset=\"100%\"";
     227           0 :           m_outputSink << " stop-color=\"" << m_style["draw:end-color"]->getStr().cstr() << "\"";
     228           0 :           m_outputSink << " stop-opacity=\"" << (m_style["libwpg:end-opacity"] ? m_style["libwpg:end-opacity"]->getDouble() : 1) << "\" />" << std::endl;
     229             :         }
     230           0 :         m_outputSink << "  </svg:linearGradient>\n";
     231             : 
     232             :         // not a simple horizontal gradient
     233           0 :         if(angle != 270)
     234             :         {
     235           0 :           m_outputSink << "  <svg:linearGradient xlink:href=\"#grad" << m_gradientIndex-1 << "\"";
     236           0 :           m_outputSink << " id=\"grad" << m_gradientIndex++ << "\" ";
     237           0 :           m_outputSink << "x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\" ";
     238           0 :           m_outputSink << "gradientTransform=\"rotate(" << angle << " .5 .5)\" ";
     239           0 :           m_outputSink << "gradientUnits=\"objectBoundingBox\" >\n";
     240           0 :           m_outputSink << "  </svg:linearGradient>\n";
     241             :         }
     242             : 
     243           0 :         m_outputSink << "</svg:defs>\n";
     244             :       }
     245             :     }
     246             :     else
     247             :     {
     248           0 :       if (m_style["draw:style"] && m_style["draw:style"]->getStr() == "radial")
     249             :       {
     250           0 :         m_outputSink << "<svg:defs>\n";
     251           0 :         m_outputSink << "  <svg:radialGradient id=\"grad" << m_gradientIndex++ << "\" cx=\"" << m_style["svg:cx"]->getStr().cstr() << "\" cy=\"" << m_style["svg:cy"]->getStr().cstr() << "\" r=\"" << m_style["svg:r"]->getStr().cstr() << "\" >\n";
     252           0 :         for(unsigned c = 0; c < m_gradient.count(); c++)
     253             :         {
     254           0 :           m_outputSink << "    <svg:stop offset=\"" << m_gradient[c]["svg:offset"]->getStr().cstr() << "\"";
     255             : 
     256           0 :           m_outputSink << " stop-color=\"" << m_gradient[c]["svg:stop-color"]->getStr().cstr() << "\"";
     257           0 :           m_outputSink << " stop-opacity=\"" << m_gradient[c]["svg:stop-opacity"]->getDouble() << "\" />" << std::endl;
     258             : 
     259             :         }
     260           0 :         m_outputSink << "  </svg:radialGradient>\n";
     261           0 :         m_outputSink << "</svg:defs>\n";
     262             :       }
     263             :       else
     264             :       {
     265           0 :         m_outputSink << "<svg:defs>\n";
     266           0 :         m_outputSink << "  <svg:linearGradient id=\"grad" << m_gradientIndex++ << "\" >\n";
     267           0 :         for(unsigned c = 0; c < m_gradient.count(); c++)
     268             :         {
     269           0 :           m_outputSink << "    <svg:stop offset=\"" << m_gradient[c]["svg:offset"]->getStr().cstr() << "\"";
     270             : 
     271           0 :           m_outputSink << " stop-color=\"" << m_gradient[c]["svg:stop-color"]->getStr().cstr() << "\"";
     272           0 :           m_outputSink << " stop-opacity=\"" << m_gradient[c]["svg:stop-opacity"]->getDouble() << "\" />" << std::endl;
     273             : 
     274             :         }
     275           0 :         m_outputSink << "  </svg:linearGradient>\n";
     276             : 
     277             :         // not a simple horizontal gradient
     278           0 :         if(angle != 270)
     279             :         {
     280           0 :           m_outputSink << "  <svg:linearGradient xlink:href=\"#grad" << m_gradientIndex-1 << "\"";
     281           0 :           m_outputSink << " id=\"grad" << m_gradientIndex++ << "\" ";
     282           0 :           m_outputSink << "x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\" ";
     283           0 :           m_outputSink << "gradientTransform=\"rotate(" << angle << " .5 .5)\" ";
     284           0 :           m_outputSink << "gradientUnits=\"objectBoundingBox\" >\n";
     285           0 :           m_outputSink << "  </svg:linearGradient>\n";
     286             :         }
     287             : 
     288           0 :         m_outputSink << "</svg:defs>\n";
     289             :       }
     290             :     }
     291             :   }
     292           0 :   else if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "bitmap")
     293             :   {
     294           0 :     if (m_style["draw:fill-image"] && m_style["libwpg:mime-type"])
     295             :     {
     296           0 :       m_outputSink << "<svg:defs>\n";
     297           0 :       m_outputSink << "  <svg:pattern id=\"img" << m_patternIndex++ << "\" patternUnits=\"userSpaceOnUse\" ";
     298           0 :       if (m_style["svg:width"])
     299           0 :         m_outputSink << "width=\"" << doubleToString(72*(m_style["svg:width"]->getDouble())) << "\" ";
     300             :       else
     301           0 :         m_outputSink << "width=\"100\" ";
     302             : 
     303           0 :       if (m_style["svg:height"])
     304           0 :         m_outputSink << "height=\"" << doubleToString(72*(m_style["svg:height"]->getDouble())) << "\">" << std::endl;
     305             :       else
     306           0 :         m_outputSink << "height=\"100\">" << std::endl;
     307           0 :       m_outputSink << "<svg:image ";
     308             : 
     309           0 :       if (m_style["svg:x"])
     310           0 :         m_outputSink << "x=\"" << doubleToString(72*(m_style["svg:x"]->getDouble())) << "\" ";
     311             :       else
     312           0 :         m_outputSink << "x=\"0\" ";
     313             : 
     314           0 :       if (m_style["svg:y"])
     315           0 :         m_outputSink << "y=\"" << doubleToString(72*(m_style["svg:y"]->getDouble())) << "\" ";
     316             :       else
     317           0 :         m_outputSink << "y=\"0\" ";
     318             : 
     319           0 :       if (m_style["svg:width"])
     320           0 :         m_outputSink << "width=\"" << doubleToString(72*(m_style["svg:width"]->getDouble())) << "\" ";
     321             :       else
     322           0 :         m_outputSink << "width=\"100\" ";
     323             : 
     324           0 :       if (m_style["svg:height"])
     325           0 :         m_outputSink << "height=\"" << doubleToString(72*(m_style["svg:height"]->getDouble())) << "\" ";
     326             :       else
     327           0 :         m_outputSink << "height=\"100\" ";
     328             : 
     329           0 :       m_outputSink << "xlink:href=\"data:" << m_style["libwpg:mime-type"]->getStr().cstr() << ";base64,";
     330           0 :       m_outputSink << m_style["draw:fill-image"]->getStr().cstr();
     331           0 :       m_outputSink << "\" />\n";
     332           0 :       m_outputSink << "  </svg:pattern>\n";
     333           0 :       m_outputSink << "</svg:defs>\n";
     334             :     }
     335             :   }
     336           0 : }
     337             : 
     338           0 : void libcdr::CDRSVGGenerator::startLayer(const ::WPXPropertyList &propList)
     339             : {
     340           0 :   m_outputSink << "<svg:g";
     341           0 :   if (propList["svg:id"])
     342           0 :     m_outputSink << " id=\"Layer" << propList["svg:id"]->getInt() << "\"";
     343           0 :   if (propList["svg:fill-rule"])
     344           0 :     m_outputSink << " fill-rule=\"" << propList["svg:fill-rule"]->getStr().cstr() << "\"";
     345           0 :   m_outputSink << ">\n";
     346           0 : }
     347             : 
     348           0 : void libcdr::CDRSVGGenerator::endLayer()
     349             : {
     350           0 :   m_outputSink << "</svg:g>\n";
     351           0 : }
     352             : 
     353           0 : void libcdr::CDRSVGGenerator::drawRectangle(const ::WPXPropertyList &propList)
     354             : {
     355           0 :   m_outputSink << "<svg:rect ";
     356           0 :   m_outputSink << "x=\"" << doubleToString(72*propList["svg:x"]->getDouble()) << "\" y=\"" << doubleToString(72*propList["svg:y"]->getDouble()) << "\" ";
     357           0 :   m_outputSink << "width=\"" << doubleToString(72*propList["svg:width"]->getDouble()) << "\" height=\"" << doubleToString(72*propList["svg:height"]->getDouble()) << "\" ";
     358           0 :   if((propList["svg:rx"] && propList["svg:rx"]->getInt() !=0) || (propList["svg:ry"] && propList["svg:ry"]->getInt() !=0))
     359           0 :     m_outputSink << "rx=\"" << doubleToString(72*propList["svg:rx"]->getDouble()) << "\" ry=\"" << doubleToString(72*propList["svg:ry"]->getDouble()) << "\" ";
     360           0 :   writeStyle();
     361           0 :   m_outputSink << "/>\n";
     362           0 : }
     363             : 
     364           0 : void libcdr::CDRSVGGenerator::drawEllipse(const WPXPropertyList &propList)
     365             : {
     366           0 :   m_outputSink << "<svg:ellipse ";
     367           0 :   m_outputSink << "cx=\"" << doubleToString(72*propList["svg:cx"]->getDouble()) << "\" cy=\"" << doubleToString(72*propList["svg:cy"]->getDouble()) << "\" ";
     368           0 :   m_outputSink << "rx=\"" << doubleToString(72*propList["svg:rx"]->getDouble()) << "\" ry=\"" << doubleToString(72*propList["svg:ry"]->getDouble()) << "\" ";
     369           0 :   writeStyle();
     370           0 :   if (propList["libwpg:rotate"] && propList["libwpg:rotate"]->getDouble() != 0.0)
     371           0 :     m_outputSink << " transform=\" translate(" << doubleToString(72*propList["svg:cx"]->getDouble()) << ", " << doubleToString(72*propList["svg:cy"]->getDouble())
     372           0 :                  << ") rotate(" << doubleToString(-propList["libwpg:rotate"]->getDouble())
     373           0 :                  << ") translate(" << doubleToString(-72*propList["svg:cx"]->getDouble())
     374           0 :                  << ", " << doubleToString(-72*propList["svg:cy"]->getDouble())
     375           0 :                  << ")\" ";
     376           0 :   m_outputSink << "/>\n";
     377           0 : }
     378             : 
     379           0 : void libcdr::CDRSVGGenerator::drawPolyline(const ::WPXPropertyListVector &vertices)
     380             : {
     381           0 :   drawPolySomething(vertices, false);
     382           0 : }
     383             : 
     384           0 : void libcdr::CDRSVGGenerator::drawPolygon(const ::WPXPropertyListVector &vertices)
     385             : {
     386           0 :   drawPolySomething(vertices, true);
     387           0 : }
     388             : 
     389           0 : void libcdr::CDRSVGGenerator::drawPolySomething(const ::WPXPropertyListVector &vertices, bool isClosed)
     390             : {
     391           0 :   if(vertices.count() < 2)
     392           0 :     return;
     393             : 
     394           0 :   if(vertices.count() == 2)
     395             :   {
     396           0 :     m_outputSink << "<svg:line ";
     397           0 :     m_outputSink << "x1=\"" << doubleToString(72*(vertices[0]["svg:x"]->getDouble())) << "\"  y1=\"" << doubleToString(72*(vertices[0]["svg:y"]->getDouble())) << "\" ";
     398           0 :     m_outputSink << "x2=\"" << doubleToString(72*(vertices[1]["svg:x"]->getDouble())) << "\"  y2=\"" << doubleToString(72*(vertices[1]["svg:y"]->getDouble())) << "\"\n";
     399           0 :     writeStyle();
     400           0 :     m_outputSink << "/>\n";
     401             :   }
     402             :   else
     403             :   {
     404           0 :     if (isClosed)
     405           0 :       m_outputSink << "<svg:polygon ";
     406             :     else
     407           0 :       m_outputSink << "<svg:polyline ";
     408             : 
     409           0 :     m_outputSink << "points=\"";
     410           0 :     for(unsigned i = 0; i < vertices.count(); i++)
     411             :     {
     412           0 :       m_outputSink << doubleToString(72*(vertices[i]["svg:x"]->getDouble())) << " " << doubleToString(72*(vertices[i]["svg:y"]->getDouble()));
     413           0 :       if (i < vertices.count()-1)
     414           0 :         m_outputSink << ", ";
     415             :     }
     416           0 :     m_outputSink << "\"\n";
     417           0 :     writeStyle(isClosed);
     418           0 :     m_outputSink << "/>\n";
     419             :   }
     420             : }
     421             : 
     422           0 : void libcdr::CDRSVGGenerator::drawPath(const ::WPXPropertyListVector &path)
     423             : {
     424           0 :   m_outputSink << "<svg:path d=\" ";
     425           0 :   bool isClosed = false;
     426           0 :   unsigned i=0;
     427           0 :   for(i=0; i < path.count(); i++)
     428             :   {
     429           0 :     WPXPropertyList propList = path[i];
     430           0 :     if (propList["libwpg:path-action"] && propList["libwpg:path-action"]->getStr() == "M")
     431             :     {
     432           0 :       m_outputSink << "\nM";
     433           0 :       m_outputSink << doubleToString(72*(propList["svg:x"]->getDouble())) << "," << doubleToString(72*(propList["svg:y"]->getDouble()));
     434             :     }
     435           0 :     else if (propList["libwpg:path-action"] && propList["libwpg:path-action"]->getStr() == "L")
     436             :     {
     437           0 :       m_outputSink << "\nL";
     438           0 :       m_outputSink << doubleToString(72*(propList["svg:x"]->getDouble())) << "," << doubleToString(72*(propList["svg:y"]->getDouble()));
     439             :     }
     440           0 :     else if (propList["libwpg:path-action"] && propList["libwpg:path-action"]->getStr() == "C")
     441             :     {
     442           0 :       m_outputSink << "\nC";
     443           0 :       m_outputSink << doubleToString(72*(propList["svg:x1"]->getDouble())) << "," << doubleToString(72*(propList["svg:y1"]->getDouble())) << " ";
     444           0 :       m_outputSink << doubleToString(72*(propList["svg:x2"]->getDouble())) << "," << doubleToString(72*(propList["svg:y2"]->getDouble())) << " ";
     445           0 :       m_outputSink << doubleToString(72*(propList["svg:x"]->getDouble())) << "," << doubleToString(72*(propList["svg:y"]->getDouble()));
     446             :     }
     447           0 :     else if (propList["libwpg:path-action"] && propList["libwpg:path-action"]->getStr() == "Q")
     448             :     {
     449           0 :       m_outputSink << "\nQ";
     450           0 :       m_outputSink << doubleToString(72*(propList["svg:x1"]->getDouble())) << "," << doubleToString(72*(propList["svg:y1"]->getDouble())) << " ";
     451           0 :       m_outputSink << doubleToString(72*(propList["svg:x"]->getDouble())) << "," << doubleToString(72*(propList["svg:y"]->getDouble()));
     452             :     }
     453           0 :     else if (propList["libwpg:path-action"] && propList["libwpg:path-action"]->getStr() == "A")
     454             :     {
     455           0 :       m_outputSink << "\nA";
     456           0 :       m_outputSink << doubleToString(72*(propList["svg:rx"]->getDouble())) << "," << doubleToString(72*(propList["svg:ry"]->getDouble())) << " ";
     457           0 :       m_outputSink << doubleToString(propList["libwpg:rotate"] ? propList["libwpg:rotate"]->getDouble() : 0) << " ";
     458           0 :       m_outputSink << (propList["libwpg:large-arc"] ? propList["libwpg:large-arc"]->getInt() : 1) << ",";
     459           0 :       m_outputSink << (propList["libwpg:sweep"] ? propList["libwpg:sweep"]->getInt() : 1) << " ";
     460           0 :       m_outputSink << doubleToString(72*(propList["svg:x"]->getDouble())) << "," << doubleToString(72*(propList["svg:y"]->getDouble()));
     461             :     }
     462           0 :     else if ((i >= path.count()-1 && i > 2) && propList["libwpg:path-action"] && propList["libwpg:path-action"]->getStr() == "Z" )
     463             :     {
     464           0 :       isClosed = true;
     465           0 :       m_outputSink << "\nZ";
     466             :     }
     467           0 :   }
     468             : 
     469           0 :   m_outputSink << "\" \n";
     470           0 :   writeStyle(isClosed);
     471           0 :   m_outputSink << "/>\n";
     472           0 : }
     473             : 
     474           0 : void libcdr::CDRSVGGenerator::drawGraphicObject(const ::WPXPropertyList &propList, const ::WPXBinaryData &binaryData)
     475             : {
     476           0 :   if (!propList["libwpg:mime-type"] || propList["libwpg:mime-type"]->getStr().len() <= 0)
     477           0 :     return;
     478           0 :   WPXString base64 = binaryData.getBase64Data();
     479           0 :   m_outputSink << "<svg:image ";
     480           0 :   if (propList["svg:x"] && propList["svg:y"] && propList["svg:width"] && propList["svg:height"])
     481           0 :     m_outputSink << "x=\"" << doubleToString(72*(propList["svg:x"]->getDouble())) << "\" y=\"" << doubleToString(72*(propList["svg:y"]->getDouble())) << "\" ";
     482           0 :   m_outputSink << "width=\"" << doubleToString(72*(propList["svg:width"]->getDouble())) << "\" height=\"" << doubleToString(72*(propList["svg:height"]->getDouble())) << "\" ";
     483           0 :   m_outputSink << "xlink:href=\"data:" << propList["libwpg:mime-type"]->getStr().cstr() << ";base64,";
     484           0 :   m_outputSink << base64.cstr();
     485           0 :   m_outputSink << "\" />\n";
     486             : }
     487             : 
     488           0 : void libcdr::CDRSVGGenerator::startTextObject(const ::WPXPropertyList &propList, const ::WPXPropertyListVector & /* path */)
     489             : {
     490           0 :   m_outputSink << "<svg:text ";
     491           0 :   if (propList["svg:x"] && propList["svg:y"])
     492           0 :     m_outputSink << "x=\"" << doubleToString(72*(propList["svg:x"]->getDouble())) << "\" y=\"" << doubleToString(72*(propList["svg:y"]->getDouble())) << "\"";
     493           0 :   if (propList["libwpg:rotate"] && propList["libwpg:rotate"]->getDouble() != 0.0)
     494           0 :     m_outputSink << " transform=\"translate(" << doubleToString(72*propList["svg:x"]->getDouble()) << ", " << doubleToString(72*propList["svg:y"]->getDouble())
     495           0 :                  << ") rotate(" << doubleToString(-propList["libwpg:rotate"]->getDouble())
     496           0 :                  << ") translate(" << doubleToString(-72*propList["svg:x"]->getDouble())
     497           0 :                  << ", " << doubleToString(-72*propList["svg:y"]->getDouble())
     498           0 :                  << ")\"";
     499           0 :   m_outputSink << ">\n";
     500             : 
     501           0 : }
     502             : 
     503           0 : void libcdr::CDRSVGGenerator::endTextObject()
     504             : {
     505           0 :   m_outputSink << "</svg:text>\n";
     506           0 : }
     507             : 
     508           0 : void libcdr::CDRSVGGenerator::startTextSpan(const ::WPXPropertyList &propList)
     509             : {
     510           0 :   m_outputSink << "<svg:tspan ";
     511           0 :   if (propList["style:font-name"])
     512           0 :     m_outputSink << "font-family=\"" << propList["style:font-name"]->getStr().cstr() << "\" ";
     513           0 :   if (propList["fo:font-style"])
     514           0 :     m_outputSink << "font-style=\"" << propList["fo:font-style"]->getStr().cstr() << "\" ";
     515           0 :   if (propList["fo:font-weight"])
     516           0 :     m_outputSink << "font-weight=\"" << propList["fo:font-weight"]->getStr().cstr() << "\" ";
     517           0 :   if (propList["fo:font-variant"])
     518           0 :     m_outputSink << "font-variant=\"" << propList["fo:font-variant"]->getStr().cstr() << "\" ";
     519           0 :   if (propList["fo:font-size"])
     520           0 :     m_outputSink << "font-size=\"" << doubleToString(propList["fo:font-size"]->getDouble()) << "\" ";
     521           0 :   if (propList["fo:color"])
     522           0 :     m_outputSink << "fill=\"" << propList["fo:color"]->getStr().cstr() << "\" ";
     523           0 :   if (propList["fo:text-transform"])
     524           0 :     m_outputSink << "text-transform=\"" << propList["fo:text-transform"]->getStr().cstr() << "\" ";
     525           0 :   if (propList["svg:fill-opacity"])
     526           0 :     m_outputSink << "fill-opacity=\"" << doubleToString(propList["svg:fill-opacity"]->getDouble()) << "\" ";
     527           0 :   if (propList["svg:stroke-opacity"])
     528           0 :     m_outputSink << "stroke-opacity=\"" << doubleToString(propList["svg:stroke-opacity"]->getDouble()) << "\" ";
     529           0 :   m_outputSink << ">\n";
     530           0 : }
     531             : 
     532           0 : void libcdr::CDRSVGGenerator::endTextSpan()
     533             : {
     534           0 :   m_outputSink << "</svg:tspan>\n";
     535           0 : }
     536             : 
     537           0 : void libcdr::CDRSVGGenerator::insertText(const ::WPXString &str)
     538             : {
     539           0 :   WPXString tempUTF8(str, true);
     540           0 :   m_outputSink << tempUTF8.cstr() << "\n";
     541           0 : }
     542             : 
     543             : // create "style" attribute based on current pen and brush
     544           0 : void libcdr::CDRSVGGenerator::writeStyle(bool /* isClosed */)
     545             : {
     546           0 :   m_outputSink << "style=\"";
     547             : 
     548           0 :   if (m_style["svg:stroke-width"])
     549             :   {
     550           0 :     double width = m_style["svg:stroke-width"]->getDouble();
     551           0 :     if (width == 0.0 && m_style["draw:stroke"] && m_style["draw:stroke"]->getStr() != "none")
     552           0 :       width = 0.2 / 72.0; // reasonable hairline
     553           0 :     m_outputSink << "stroke-width: " << doubleToString(72*width) << "; ";
     554             :   }
     555           0 :   if ((m_style["draw:stroke"] && m_style["draw:stroke"]->getStr() != "none"))
     556             :   {
     557           0 :     if (m_style["svg:stroke-color"])
     558           0 :       m_outputSink << "stroke: " << m_style["svg:stroke-color"]->getStr().cstr()  << "; ";
     559           0 :     if(m_style["svg:stroke-opacity"] &&  m_style["svg:stroke-opacity"]->getInt()!= 1)
     560           0 :       m_outputSink << "stroke-opacity: " << doubleToString(m_style["svg:stroke-opacity"]->getDouble()) << "; ";
     561             :   }
     562             : 
     563           0 :   if (m_style["draw:stroke"] && m_style["draw:stroke"]->getStr() == "solid")
     564           0 :     m_outputSink << "stroke-dasharray:  solid; ";
     565           0 :   else if (m_style["draw:stroke"] && m_style["draw:stroke"]->getStr() == "dash")
     566             :   {
     567           0 :     int dots1 = m_style["draw:dots1"]->getInt();
     568           0 :     int dots2 = m_style["draw:dots2"]->getInt();
     569           0 :     double dots1len = m_style["draw:dots1-length"]->getDouble();
     570           0 :     double dots2len = m_style["draw:dots2-length"]->getDouble();
     571           0 :     double gap = m_style["draw:distance"]->getDouble();
     572           0 :     m_outputSink << "stroke-dasharray: ";
     573           0 :     for (int i = 0; i < dots1; i++)
     574             :     {
     575           0 :       if (i)
     576           0 :         m_outputSink << ", ";
     577           0 :       m_outputSink << (int)dots1len;
     578           0 :       m_outputSink << ", ";
     579           0 :       m_outputSink << (int)gap;
     580             :     }
     581           0 :     for (int j = 0; j < dots2; j++)
     582             :     {
     583           0 :       m_outputSink << ", ";
     584           0 :       m_outputSink << (int)dots2len;
     585           0 :       m_outputSink << ", ";
     586           0 :       m_outputSink << (int)gap;
     587             :     }
     588           0 :     m_outputSink << "; ";
     589             :   }
     590             : 
     591           0 :   if (m_style["svg:stroke-linecap"])
     592           0 :     m_outputSink << "stroke-linecap: " << m_style["svg:stroke-linecap"]->getStr().cstr() << "; ";
     593             : 
     594           0 :   if (m_style["svg:stroke-linejoin"])
     595           0 :     m_outputSink << "stroke-linejoin: " << m_style["svg:stroke-linejoin"]->getStr().cstr() << "; ";
     596             : 
     597           0 :   if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "none")
     598           0 :     m_outputSink << "fill: none; ";
     599           0 :   else if(m_style["svg:fill-rule"])
     600           0 :     m_outputSink << "fill-rule: " << m_style["svg:fill-rule"]->getStr().cstr() << "; ";
     601             : 
     602           0 :   if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "gradient")
     603           0 :     m_outputSink << "fill: url(#grad" << m_gradientIndex-1 << "); ";
     604             : 
     605           0 :   if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "bitmap")
     606           0 :     m_outputSink << "fill: url(#img" << m_patternIndex-1 << "); ";
     607             : 
     608           0 :   if(m_style["draw:shadow"] && m_style["draw:shadow"]->getStr() == "visible")
     609           0 :     m_outputSink << "filter:url(#shadow" << m_shadowIndex-1 << "); ";
     610             : 
     611           0 :   if(m_style["draw:fill"] && m_style["draw:fill"]->getStr() == "solid")
     612           0 :     if (m_style["draw:fill-color"])
     613           0 :       m_outputSink << "fill: " << m_style["draw:fill-color"]->getStr().cstr() << "; ";
     614           0 :   if(m_style["draw:opacity"] && m_style["draw:opacity"]->getDouble() < 1)
     615           0 :     m_outputSink << "fill-opacity: " << doubleToString(m_style["draw:opacity"]->getDouble()) << "; ";
     616           0 :   m_outputSink << "\""; // style
     617           0 : }
     618             : /* vim:set shiftwidth=2 softtabstop=2 expandtab: */

Generated by: LCOV version 1.10