LCOV - code coverage report
Current view: top level - libreoffice/writerperfect/source/filter - OdgGenerator.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 1029 0.0 %
Date: 2012-12-27 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       6             :  *
       7             :  * For further information visit http://libwpg.sourceforge.net
       8             :  */
       9             : 
      10             : #include "FilterInternal.hxx"
      11             : 
      12             : #include "OdgGenerator.hxx"
      13             : #include "DocumentElement.hxx"
      14             : #include "OdfDocumentHandler.hxx"
      15             : #include "TextRunStyle.hxx"
      16             : #include "FontStyle.hxx"
      17             : #include <locale.h>
      18             : #include <math.h>
      19             : #include <string>
      20             : #include <map>
      21             : 
      22             : #ifndef M_PI
      23             : #define M_PI 3.14159265358979323846
      24             : #endif
      25             : 
      26             : // Workaround for the incapacity of draw to have multiple page
      27             : // sizes in the same document. Once that limitation is lifted,
      28             : // remove this
      29             : #define MULTIPAGE_WORKAROUND 1
      30             : 
      31             : namespace
      32             : {
      33             : 
      34           0 : static inline double getAngle(double bx, double by)
      35             : {
      36           0 :     return fmod(2*M_PI + (by > 0.0 ? 1.0 : -1.0) * acos( bx / sqrt(bx * bx + by * by) ), 2*M_PI);
      37             : }
      38             : 
      39           0 : static void getEllipticalArcBBox(double x0, double y0,
      40             :                                  double rx, double ry, double phi, bool largeArc, bool sweep, double x, double y,
      41             :                                  double &xmin, double &ymin, double &xmax, double &ymax)
      42             : {
      43           0 :     phi *= M_PI/180;
      44           0 :     if (rx < 0.0)
      45           0 :         rx *= -1.0;
      46           0 :     if (ry < 0.0)
      47           0 :         ry *= -1.0;
      48             : 
      49           0 :     if (rx == 0.0 || ry == 0.0)
      50             :     {
      51           0 :         xmin = (x0 < x ? x0 : x);
      52           0 :         xmax = (x0 > x ? x0 : x);
      53           0 :         ymin = (y0 < y ? y0 : y);
      54           0 :         ymax = (y0 > y ? y0 : y);
      55             :         return;
      56             :     }
      57             : 
      58             :     // F.6.5.1
      59           0 :     const double x1prime = cos(phi)*(x0 - x)/2 + sin(phi)*(y0 - y)/2;
      60           0 :     const double y1prime = -sin(phi)*(x0 - x)/2 + cos(phi)*(y0 - y)/2;
      61             : 
      62             :     // F.6.5.2
      63           0 :     double radicant = (rx*rx*ry*ry - rx*rx*y1prime*y1prime - ry*ry*x1prime*x1prime)/(rx*rx*y1prime*y1prime + ry*ry*x1prime*x1prime);
      64           0 :     double cxprime = 0.0;
      65           0 :     double cyprime = 0.0;
      66           0 :     if (radicant < 0.0)
      67             :     {
      68           0 :         double ratio = rx/ry;
      69           0 :         radicant = y1prime*y1prime + x1prime*x1prime/(ratio*ratio);
      70           0 :         if (radicant < 0.0)
      71             :         {
      72           0 :             xmin = (x0 < x ? x0 : x);
      73           0 :             xmax = (x0 > x ? x0 : x);
      74           0 :             ymin = (y0 < y ? y0 : y);
      75           0 :             ymax = (y0 > y ? y0 : y);
      76             :             return;
      77             :         }
      78           0 :         ry=sqrt(radicant);
      79           0 :         rx=ratio*ry;
      80             :     }
      81             :     else
      82             :     {
      83           0 :         double factor = (largeArc==sweep ? -1.0 : 1.0)*sqrt(radicant);
      84             : 
      85           0 :         cxprime = factor*rx*y1prime/ry;
      86           0 :         cyprime = -factor*ry*x1prime/rx;
      87             :     }
      88             : 
      89             :     // F.6.5.3
      90           0 :     double cx = cxprime*cos(phi) - cyprime*sin(phi) + (x0 + x)/2;
      91           0 :     double cy = cxprime*sin(phi) + cyprime*cos(phi) + (y0 + y)/2;
      92             : 
      93             :     // now compute bounding box of the whole ellipse
      94             : 
      95             :     // Parametric equation of an ellipse:
      96             :     // x(theta) = cx + rx*cos(theta)*cos(phi) - ry*sin(theta)*sin(phi)
      97             :     // y(theta) = cy + rx*cos(theta)*sin(phi) + ry*sin(theta)*cos(phi)
      98             : 
      99             :     // Compute local extrems
     100             :     // 0 = -rx*sin(theta)*cos(phi) - ry*cos(theta)*sin(phi)
     101             :     // 0 = -rx*sin(theta)*sin(phi) - ry*cos(theta)*cos(phi)
     102             : 
     103             :     // Local extrems for X:
     104             :     // theta = -atan(ry*tan(phi)/rx)
     105             :     // and
     106             :     // theta = M_PI -atan(ry*tan(phi)/rx)
     107             : 
     108             :     // Local extrems for Y:
     109             :     // theta = atan(ry/(tan(phi)*rx))
     110             :     // and
     111             :     // theta = M_PI + atan(ry/(tan(phi)*rx))
     112             : 
     113             :     double txmin, txmax, tymin, tymax;
     114             : 
     115             :     // First handle special cases
     116           0 :     if (phi == 0 || phi == M_PI)
     117             :     {
     118           0 :         xmin = cx - rx;
     119           0 :         txmin = getAngle(-rx, 0);
     120           0 :         xmax = cx + rx;
     121           0 :         txmax = getAngle(rx, 0);
     122           0 :         ymin = cy - ry;
     123           0 :         tymin = getAngle(0, -ry);
     124           0 :         ymax = cy + ry;
     125           0 :         tymax = getAngle(0, ry);
     126             :     }
     127           0 :     else if (phi == M_PI / 2.0 || phi == 3.0*M_PI/2.0)
     128             :     {
     129           0 :         xmin = cx - ry;
     130           0 :         txmin = getAngle(-ry, 0);
     131           0 :         xmax = cx + ry;
     132           0 :         txmax = getAngle(ry, 0);
     133           0 :         ymin = cy - rx;
     134           0 :         tymin = getAngle(0, -rx);
     135           0 :         ymax = cy + rx;
     136           0 :         tymax = getAngle(0, rx);
     137             :     }
     138             :     else
     139             :     {
     140           0 :         txmin = -atan(ry*tan(phi)/rx);
     141           0 :         txmax = M_PI - atan (ry*tan(phi)/rx);
     142           0 :         xmin = cx + rx*cos(txmin)*cos(phi) - ry*sin(txmin)*sin(phi);
     143           0 :         xmax = cx + rx*cos(txmax)*cos(phi) - ry*sin(txmax)*sin(phi);
     144           0 :         double tmpY = cy + rx*cos(txmin)*sin(phi) + ry*sin(txmin)*cos(phi);
     145           0 :         txmin = getAngle(xmin - cx, tmpY - cy);
     146           0 :         tmpY = cy + rx*cos(txmax)*sin(phi) + ry*sin(txmax)*cos(phi);
     147           0 :         txmax = getAngle(xmax - cx, tmpY - cy);
     148             : 
     149           0 :         tymin = atan(ry/(tan(phi)*rx));
     150           0 :         tymax = atan(ry/(tan(phi)*rx))+M_PI;
     151           0 :         ymin = cy + rx*cos(tymin)*sin(phi) + ry*sin(tymin)*cos(phi);
     152           0 :         ymax = cy + rx*cos(tymax)*sin(phi) + ry*sin(tymax)*cos(phi);
     153           0 :         double tmpX = cx + rx*cos(tymin)*cos(phi) - ry*sin(tymin)*sin(phi);
     154           0 :         tymin = getAngle(tmpX - cx, ymin - cy);
     155           0 :         tmpX = cx + rx*cos(tymax)*cos(phi) - ry*sin(tymax)*sin(phi);
     156           0 :         tymax = getAngle(tmpX - cx, ymax - cy);
     157             :     }
     158           0 :     if (xmin > xmax)
     159             :     {
     160           0 :         std::swap(xmin,xmax);
     161           0 :         std::swap(txmin,txmax);
     162             :     }
     163           0 :     if (ymin > ymax)
     164             :     {
     165           0 :         std::swap(ymin,ymax);
     166           0 :         std::swap(tymin,tymax);
     167             :     }
     168           0 :     double angle1 = getAngle(x0 - cx, y0 - cy);
     169           0 :     double angle2 = getAngle(x - cx, y - cy);
     170             : 
     171             :     // for sweep == 0 it is normal to have delta theta < 0
     172             :     // but we don't care about the rotation direction for bounding box
     173           0 :     if (!sweep)
     174           0 :         std::swap(angle1, angle2);
     175             : 
     176             :     // We cannot check directly for whether an angle is included in
     177             :     // an interval of angles that cross the 360/0 degree boundary
     178             :     // So here we will have to check for their absence in the complementary
     179             :     // angle interval
     180           0 :     bool otherArc = false;
     181           0 :     if (angle1 > angle2)
     182             :     {
     183           0 :         std::swap(angle1, angle2);
     184           0 :         otherArc = true;
     185             :     }
     186             : 
     187             :     // Check txmin
     188           0 :     if ((!otherArc && (angle1 > txmin || angle2 < txmin)) || (otherArc && !(angle1 > txmin || angle2 < txmin)))
     189           0 :         xmin = x0 < x ? x0 : x;
     190             :     // Check txmax
     191           0 :     if ((!otherArc && (angle1 > txmax || angle2 < txmax)) || (otherArc && !(angle1 > txmax || angle2 < txmax)))
     192           0 :         xmax = x0 > x ? x0 : x;
     193             :     // Check tymin
     194           0 :     if ((!otherArc && (angle1 > tymin || angle2 < tymin)) || (otherArc && !(angle1 > tymin || angle2 < tymin)))
     195           0 :         ymin = y0 < y ? y0 : y;
     196             :     // Check tymax
     197           0 :     if ((!otherArc && (angle1 > tymax || angle2 < tymax)) || (otherArc && !(angle1 > tymax || angle2 < tymax)))
     198           0 :         ymax = y0 > y ? y0 : y;
     199             : }
     200             : 
     201           0 : static inline double quadraticExtreme(double t, double a, double b, double c)
     202             : {
     203           0 :     return (1.0-t)*(1.0-t)*a + 2.0*(1.0-t)*t*b + t*t*c;
     204             : }
     205             : 
     206           0 : static inline double quadraticDerivative(double a, double b, double c)
     207             : {
     208           0 :     double denominator = a - 2.0*b + c;
     209           0 :     if (fabs(denominator) != 0.0)
     210           0 :         return (a - b)/denominator;
     211           0 :     return -1.0;
     212             : }
     213             : 
     214           0 : static void getQuadraticBezierBBox(double x0, double y0, double x1, double y1, double x, double y,
     215             :                                    double &xmin, double &ymin, double &xmax, double &ymax)
     216             : {
     217           0 :     xmin = x0 < x ? x0 : x;
     218           0 :     xmax = x0 > x ? x0 : x;
     219           0 :     ymin = y0 < y ? y0 : y;
     220           0 :     ymax = y0 > y ? y0 : y;
     221             : 
     222           0 :     double t = quadraticDerivative(x0, x1, x);
     223           0 :     if(t>=0 && t<=1)
     224             :     {
     225           0 :         double tmpx = quadraticExtreme(t, x0, x1, x);
     226           0 :         xmin = tmpx < xmin ? tmpx : xmin;
     227           0 :         xmax = tmpx > xmax ? tmpx : xmax;
     228             :     }
     229             : 
     230           0 :     t = quadraticDerivative(y0, y1, y);
     231           0 :     if(t>=0 && t<=1)
     232             :     {
     233           0 :         double tmpy = quadraticExtreme(t, y0, y1, y);
     234           0 :         ymin = tmpy < ymin ? tmpy : ymin;
     235           0 :         ymax = tmpy > ymax ? tmpy : ymax;
     236             :     }
     237           0 : }
     238             : 
     239           0 : static inline double cubicBase(double t, double a, double b, double c, double d)
     240             : {
     241           0 :     return (1.0-t)*(1.0-t)*(1.0-t)*a + 3.0*(1.0-t)*(1.0-t)*t*b + 3.0*(1.0-t)*t*t*c + t*t*t*d;
     242             : }
     243             : 
     244           0 : static void getCubicBezierBBox(double x0, double y0, double x1, double y1, double x2, double y2, double x, double y,
     245             :                                double &xmin, double &ymin, double &xmax, double &ymax)
     246             : {
     247           0 :     xmin = x0 < x ? x0 : x;
     248           0 :     xmax = x0 > x ? x0 : x;
     249           0 :     ymin = y0 < y ? y0 : y;
     250           0 :     ymax = y0 > y ? y0 : y;
     251             : 
     252           0 :     for (double t = 0.0; t <= 1.0; t+=0.01)
     253             :     {
     254           0 :         double tmpx = cubicBase(t, x0, x1, x2, x);
     255           0 :         xmin = tmpx < xmin ? tmpx : xmin;
     256           0 :         xmax = tmpx > xmax ? tmpx : xmax;
     257           0 :         double tmpy = cubicBase(t, y0, y1, y2, y);
     258           0 :         ymin = tmpy < ymin ? tmpy : ymin;
     259           0 :         ymax = tmpy > ymax ? tmpy : ymax;
     260             :     }
     261           0 : }
     262             : 
     263             : 
     264           0 : static WPXString doubleToString(const double value)
     265             : {
     266           0 :     WPXString tempString;
     267           0 :     tempString.sprintf("%.4f", value);
     268             : #ifndef ANDROID
     269           0 :     std::string decimalPoint(localeconv()->decimal_point);
     270             : #else
     271             :     std::string decimalPoint(".");
     272             : #endif
     273           0 :     if (decimalPoint.empty() || (decimalPoint == "."))
     274           0 :         return tempString;
     275           0 :     std::string stringValue(tempString.cstr());
     276           0 :     if (!stringValue.empty())
     277             :     {
     278             :         std::string::size_type pos;
     279           0 :         while ((pos = stringValue.find(decimalPoint)) != std::string::npos)
     280           0 :             stringValue.replace(pos,decimalPoint.size(),".");
     281             :     }
     282           0 :     return WPXString(stringValue.c_str());
     283             : }
     284             : 
     285             : } // anonymous namespace
     286             : 
     287             : class OdgGeneratorPrivate
     288             : {
     289             : public:
     290             :     OdgGeneratorPrivate(OdfDocumentHandler *pHandler, const OdfStreamType streamType);
     291             :     ~OdgGeneratorPrivate();
     292             :     void _writeGraphicsStyle();
     293             :     void _drawPolySomething(const ::WPXPropertyListVector &vertices, bool isClosed);
     294             :     void _drawPath(const WPXPropertyListVector &path);
     295             :     // body elements
     296             :     std::vector <DocumentElement *> mBodyElements;
     297             : 
     298             :     // graphics styles
     299             :     std::vector<DocumentElement *> mGraphicsStrokeDashStyles;
     300             :     std::vector<DocumentElement *> mGraphicsGradientStyles;
     301             :     std::vector<DocumentElement *> mGraphicsBitmapStyles;
     302             :     std::vector<DocumentElement *> mGraphicsMarkerStyles;
     303             :     std::vector<DocumentElement *> mGraphicsAutomaticStyles;
     304             : 
     305             :     // page styles
     306             :     std::vector<DocumentElement *> mPageAutomaticStyles;
     307             :     std::vector<DocumentElement *> mPageMasterStyles;
     308             : 
     309             :     // paragraph styles
     310             :     ParagraphStyleManager mParagraphManager;
     311             : 
     312             :     // span styles
     313             :     SpanStyleManager mSpanManager;
     314             : 
     315             :     // font styles
     316             :     FontStyleManager mFontManager;
     317             : 
     318             :     OdfDocumentHandler *mpHandler;
     319             : 
     320             :     ::WPXPropertyList mxStyle;
     321             :     ::WPXPropertyListVector mxGradient;
     322             :     ::WPXPropertyListVector mxMarker;
     323             :     int miGradientIndex;
     324             :     int miBitmapIndex;
     325             :     int miStartMarkerIndex;
     326             :     int miEndMarkerIndex;
     327             :     int miDashIndex;
     328             :     int miGraphicsStyleIndex;
     329             :     int miPageIndex;
     330             :     double mfWidth, mfMaxWidth;
     331             :     double mfHeight, mfMaxHeight;
     332             : 
     333             :     const OdfStreamType mxStreamType;
     334             : 
     335             :     bool mbIsTextBox;
     336             :     bool mbIsTextLine;
     337             :     bool mbIsTextOnPath;
     338             : };
     339             : 
     340           0 : OdgGeneratorPrivate::OdgGeneratorPrivate(OdfDocumentHandler *pHandler, const OdfStreamType streamType):
     341             :     mBodyElements(),
     342             :     mGraphicsStrokeDashStyles(),
     343             :     mGraphicsGradientStyles(),
     344             :     mGraphicsBitmapStyles(),
     345             :     mGraphicsAutomaticStyles(),
     346             :     mPageAutomaticStyles(),
     347             :     mPageMasterStyles(),
     348             :     mParagraphManager(),
     349             :     mSpanManager(),
     350             :     mFontManager(),
     351             :     mpHandler(pHandler),
     352             :     mxStyle(), mxGradient(),
     353             :     mxMarker(),
     354             :     miGradientIndex(1),
     355             :     miBitmapIndex(1),
     356             :     miStartMarkerIndex(1),
     357             :     miEndMarkerIndex(1),
     358             :     miDashIndex(1),
     359             :     miGraphicsStyleIndex(1),
     360             :     miPageIndex(1),
     361             :     mfWidth(0.0),
     362             :     mfMaxWidth(0.0),
     363             :     mfHeight(0.0),
     364             :     mfMaxHeight(0.0),
     365             :     mxStreamType(streamType),
     366             :     mbIsTextBox(false),
     367             :     mbIsTextLine(false),
     368           0 :     mbIsTextOnPath(false)
     369             : {
     370           0 : }
     371             : 
     372           0 : OdgGeneratorPrivate::~OdgGeneratorPrivate()
     373             : {
     374             : 
     375           0 :     for (std::vector<DocumentElement *>::iterator iterBody = mBodyElements.begin(); iterBody != mBodyElements.end(); ++iterBody)
     376             :     {
     377           0 :         delete (*iterBody);
     378           0 :         (*iterBody) = 0;
     379             :     }
     380             : 
     381           0 :     for (std::vector<DocumentElement *>::iterator iterGraphicsAutomaticStyles = mGraphicsAutomaticStyles.begin();
     382           0 :             iterGraphicsAutomaticStyles != mGraphicsAutomaticStyles.end(); ++iterGraphicsAutomaticStyles)
     383             :     {
     384           0 :         delete((*iterGraphicsAutomaticStyles));
     385             :     }
     386             : 
     387           0 :     for (std::vector<DocumentElement *>::iterator iterGraphicsStrokeDashStyles = mGraphicsStrokeDashStyles.begin();
     388           0 :             iterGraphicsStrokeDashStyles != mGraphicsStrokeDashStyles.end(); ++iterGraphicsStrokeDashStyles)
     389             :     {
     390           0 :         delete((*iterGraphicsStrokeDashStyles));
     391             :     }
     392             : 
     393           0 :     for (std::vector<DocumentElement *>::iterator iterGraphicsGradientStyles = mGraphicsGradientStyles.begin();
     394           0 :             iterGraphicsGradientStyles != mGraphicsGradientStyles.end(); ++iterGraphicsGradientStyles)
     395             :     {
     396           0 :         delete((*iterGraphicsGradientStyles));
     397             :     }
     398             : 
     399           0 :     for (std::vector<DocumentElement *>::iterator iterGraphicsBitmapStyles = mGraphicsBitmapStyles.begin();
     400           0 :             iterGraphicsBitmapStyles != mGraphicsBitmapStyles.end(); ++iterGraphicsBitmapStyles)
     401             :     {
     402           0 :         delete((*iterGraphicsBitmapStyles));
     403             :     }
     404             : 
     405           0 :     for (std::vector<DocumentElement *>::iterator iterGraphicsMarkerStyles = mGraphicsMarkerStyles.begin();
     406           0 :             iterGraphicsMarkerStyles != mGraphicsMarkerStyles.end(); ++iterGraphicsMarkerStyles)
     407             :     {
     408           0 :         delete((*iterGraphicsMarkerStyles));
     409             :     }
     410             : 
     411           0 :     for (std::vector<DocumentElement *>::iterator iterPageAutomaticStyles = mPageAutomaticStyles.begin();
     412           0 :             iterPageAutomaticStyles != mPageAutomaticStyles.end(); ++iterPageAutomaticStyles)
     413             :     {
     414           0 :         delete((*iterPageAutomaticStyles));
     415             :     }
     416             : 
     417           0 :     for (std::vector<DocumentElement *>::iterator iterPageMasterStyles = mPageMasterStyles.begin();
     418           0 :             iterPageMasterStyles != mPageMasterStyles.end(); ++iterPageMasterStyles)
     419             :     {
     420           0 :         delete((*iterPageMasterStyles));
     421             :     }
     422             : 
     423           0 :     mParagraphManager.clean();
     424           0 :     mSpanManager.clean();
     425           0 :     mFontManager.clean();
     426           0 : }
     427             : 
     428             : 
     429           0 : OdgGenerator::OdgGenerator(OdfDocumentHandler *pHandler, const OdfStreamType streamType):
     430           0 :     mpImpl(new OdgGeneratorPrivate(pHandler, streamType))
     431             : {
     432           0 :     mpImpl->mpHandler->startDocument();
     433             :     TagOpenElement tmpOfficeDocumentContent(
     434             :         (mpImpl->mxStreamType == ODF_FLAT_XML) ? "office:document" : (
     435             :             (mpImpl->mxStreamType == ODF_CONTENT_XML) ? "office:document-content" : (
     436             :                 (mpImpl->mxStreamType == ODF_STYLES_XML) ? "office:document-styles" : (
     437             :                     (mpImpl->mxStreamType == ODF_SETTINGS_XML) ? "office:document-settings" : (
     438           0 :                         (mpImpl->mxStreamType == ODF_META_XML) ? "office:document-meta" : "office:document" )))));
     439           0 :     tmpOfficeDocumentContent.addAttribute("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0");
     440           0 :     tmpOfficeDocumentContent.addAttribute("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0");
     441           0 :     tmpOfficeDocumentContent.addAttribute("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0");
     442           0 :     tmpOfficeDocumentContent.addAttribute("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0");
     443           0 :     tmpOfficeDocumentContent.addAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/");
     444           0 :     tmpOfficeDocumentContent.addAttribute("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0");
     445           0 :     tmpOfficeDocumentContent.addAttribute("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0");
     446           0 :     tmpOfficeDocumentContent.addAttribute("xmlns:config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0");
     447           0 :     tmpOfficeDocumentContent.addAttribute("xmlns:ooo", "http://openoffice.org/2004/office");
     448           0 :     tmpOfficeDocumentContent.addAttribute("office:version", "1.0");
     449           0 :     if (mpImpl->mxStreamType == ODF_FLAT_XML)
     450           0 :         tmpOfficeDocumentContent.addAttribute("office:mimetype", "application/vnd.oasis.opendocument.graphics");
     451           0 :     tmpOfficeDocumentContent.write(mpImpl->mpHandler);
     452           0 : }
     453             : 
     454           0 : OdgGenerator::~OdgGenerator()
     455             : {
     456           0 :     if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_SETTINGS_XML))
     457             :     {
     458           0 :         TagOpenElement("office:settings").write(mpImpl->mpHandler);
     459             : 
     460           0 :         TagOpenElement configItemSetOpenElement("config:config-item-set");
     461           0 :         configItemSetOpenElement.addAttribute("config:name", "ooo:view-settings");
     462           0 :         configItemSetOpenElement.write(mpImpl->mpHandler);
     463             : 
     464           0 :         TagOpenElement configItemOpenElement("config:config-item");
     465             : 
     466           0 :         configItemOpenElement.addAttribute("config:name", "VisibleAreaTop");
     467           0 :         configItemOpenElement.addAttribute("config:type", "int");
     468           0 :         configItemOpenElement.write(mpImpl->mpHandler);
     469           0 :         mpImpl->mpHandler->characters("0");
     470           0 :         mpImpl->mpHandler->endElement("config:config-item");
     471             : 
     472           0 :         configItemOpenElement.addAttribute("config:name", "VisibleAreaLeft");
     473           0 :         configItemOpenElement.addAttribute("config:type", "int");
     474           0 :         configItemOpenElement.write(mpImpl->mpHandler);
     475           0 :         mpImpl->mpHandler->characters("0");
     476           0 :         mpImpl->mpHandler->endElement("config:config-item");
     477             : 
     478           0 :         configItemOpenElement.addAttribute("config:name", "VisibleAreaWidth");
     479           0 :         configItemOpenElement.addAttribute("config:type", "int");
     480           0 :         configItemOpenElement.write(mpImpl->mpHandler);
     481           0 :         WPXString sWidth;
     482           0 :         sWidth.sprintf("%li", (unsigned long)(2540 * mpImpl->mfMaxWidth));
     483           0 :         mpImpl->mpHandler->characters(sWidth);
     484           0 :         mpImpl->mpHandler->endElement("config:config-item");
     485             : 
     486           0 :         configItemOpenElement.addAttribute("config:name", "VisibleAreaHeight");
     487           0 :         configItemOpenElement.addAttribute("config:type", "int");
     488           0 :         configItemOpenElement.write(mpImpl->mpHandler);
     489           0 :         WPXString sHeight;
     490           0 :         sHeight.sprintf("%li", (unsigned long)(2540 * mpImpl->mfMaxHeight));
     491           0 :         mpImpl->mpHandler->characters(sHeight);
     492           0 :         mpImpl->mpHandler->endElement("config:config-item");
     493             : 
     494           0 :         mpImpl->mpHandler->endElement("config:config-item-set");
     495             : 
     496           0 :         mpImpl->mpHandler->endElement("office:settings");
     497             :     }
     498             : 
     499             : 
     500           0 :     if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_STYLES_XML))
     501             :     {
     502           0 :         TagOpenElement("office:styles").write(mpImpl->mpHandler);
     503             : 
     504           0 :         for (std::vector<DocumentElement *>::const_iterator iterGraphicsStrokeDashStyles = mpImpl->mGraphicsStrokeDashStyles.begin();
     505           0 :                 iterGraphicsStrokeDashStyles != mpImpl->mGraphicsStrokeDashStyles.end(); ++iterGraphicsStrokeDashStyles)
     506             :         {
     507           0 :             (*iterGraphicsStrokeDashStyles)->write(mpImpl->mpHandler);
     508             :         }
     509             : 
     510           0 :         for (std::vector<DocumentElement *>::const_iterator iterGraphicsGradientStyles = mpImpl->mGraphicsGradientStyles.begin();
     511           0 :                 iterGraphicsGradientStyles != mpImpl->mGraphicsGradientStyles.end(); ++iterGraphicsGradientStyles)
     512             :         {
     513           0 :             (*iterGraphicsGradientStyles)->write(mpImpl->mpHandler);
     514             :         }
     515             : 
     516           0 :         for (std::vector<DocumentElement *>::const_iterator iterGraphicsBitmapStyles = mpImpl->mGraphicsBitmapStyles.begin();
     517           0 :                 iterGraphicsBitmapStyles != mpImpl->mGraphicsBitmapStyles.end(); ++iterGraphicsBitmapStyles)
     518             :         {
     519           0 :             (*iterGraphicsBitmapStyles)->write(mpImpl->mpHandler);
     520             :         }
     521             : 
     522           0 :         for (std::vector<DocumentElement *>::const_iterator iterGraphicsMarkerStyles = mpImpl->mGraphicsMarkerStyles.begin();
     523           0 :                 iterGraphicsMarkerStyles != mpImpl->mGraphicsMarkerStyles.end(); ++iterGraphicsMarkerStyles)
     524             :         {
     525           0 :             (*iterGraphicsMarkerStyles)->write(mpImpl->mpHandler);
     526             :         }
     527           0 :         mpImpl->mpHandler->endElement("office:styles");
     528             :     }
     529             : 
     530             : 
     531           0 :     if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_CONTENT_XML) || (mpImpl->mxStreamType == ODF_STYLES_XML))
     532             :     {
     533           0 :         mpImpl->mFontManager.writeFontsDeclaration(mpImpl->mpHandler);
     534             : 
     535           0 :         TagOpenElement("office:automatic-styles").write(mpImpl->mpHandler);
     536             :     }
     537             : 
     538           0 :     if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_CONTENT_XML))
     539             :     {
     540             :         // writing out the graphics automatic styles
     541           0 :         for (std::vector<DocumentElement *>::iterator iterGraphicsAutomaticStyles = mpImpl->mGraphicsAutomaticStyles.begin();
     542           0 :                 iterGraphicsAutomaticStyles != mpImpl->mGraphicsAutomaticStyles.end(); ++iterGraphicsAutomaticStyles)
     543             :         {
     544           0 :             (*iterGraphicsAutomaticStyles)->write(mpImpl->mpHandler);
     545             :         }
     546           0 :         mpImpl->mParagraphManager.write(mpImpl->mpHandler);
     547           0 :         mpImpl->mSpanManager.write(mpImpl->mpHandler);
     548             :     }
     549             : #ifdef MULTIPAGE_WORKAROUND
     550           0 :     if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_STYLES_XML))
     551             :     {
     552           0 :         TagOpenElement tmpStylePageLayoutOpenElement("style:page-layout");
     553           0 :         tmpStylePageLayoutOpenElement.addAttribute("style:name", "PM0");
     554           0 :         tmpStylePageLayoutOpenElement.write(mpImpl->mpHandler);
     555             : 
     556           0 :         TagOpenElement tmpStylePageLayoutPropertiesOpenElement("style:page-layout-properties");
     557           0 :         tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-top", "0in");
     558           0 :         tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-bottom", "0in");
     559           0 :         tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-left", "0in");
     560           0 :         tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-right", "0in");
     561           0 :         WPXString sValue;
     562           0 :         sValue = doubleToString(mpImpl->mfMaxWidth);
     563           0 :         sValue.append("in");
     564           0 :         tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:page-width", sValue);
     565           0 :         sValue = doubleToString(mpImpl->mfMaxHeight);
     566           0 :         sValue.append("in");
     567           0 :         tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:page-height", sValue);
     568           0 :         tmpStylePageLayoutPropertiesOpenElement.addAttribute("style:print-orientation", "portrait");
     569           0 :         tmpStylePageLayoutPropertiesOpenElement.write(mpImpl->mpHandler);
     570             : 
     571           0 :         mpImpl->mpHandler->endElement("style:page-layout-properties");
     572             : 
     573           0 :         mpImpl->mpHandler->endElement("style:page-layout");
     574             : 
     575           0 :         TagOpenElement tmpStyleStyleOpenElement("style:style");
     576           0 :         tmpStyleStyleOpenElement.addAttribute("style:name", "dp1");
     577           0 :         tmpStyleStyleOpenElement.addAttribute("style:family", "drawing-page");
     578           0 :         tmpStyleStyleOpenElement.write(mpImpl->mpHandler);
     579             : 
     580           0 :         TagOpenElement tmpStyleDrawingPagePropertiesOpenElement("style:drawing-page-properties");
     581             :         // tmpStyleDrawingPagePropertiesOpenElement.addAttribute("draw:background-size", "border");
     582           0 :         tmpStyleDrawingPagePropertiesOpenElement.addAttribute("draw:fill", "none");
     583           0 :         tmpStyleDrawingPagePropertiesOpenElement.write(mpImpl->mpHandler);
     584             : 
     585           0 :         mpImpl->mpHandler->endElement("style:drawing-page-properties");
     586             : 
     587           0 :         mpImpl->mpHandler->endElement("style:style");
     588             :     }
     589             : #else
     590             :     if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_STYLES_XML))
     591             :     {
     592             :         // writing out the page automatic styles
     593             :         for (std::vector<DocumentElement *>::iterator iterPageAutomaticStyles = mpImpl->mPageAutomaticStyles.begin();
     594             :                 iterPageAutomaticStyles != mpImpl->mPageAutomaticStyles.end(); ++iterPageAutomaticStyles)
     595             :         {
     596             :             (*iterPageAutomaticStyles)->write(mpImpl->mpHandler);
     597             :         }
     598             :     }
     599             : #endif
     600           0 :     if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_CONTENT_XML) || (mpImpl->mxStreamType == ODF_STYLES_XML))
     601             :     {
     602           0 :         mpImpl->mpHandler->endElement("office:automatic-styles");
     603             :     }
     604             : 
     605           0 :     if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_STYLES_XML))
     606             :     {
     607           0 :         TagOpenElement("office:master-styles").write(mpImpl->mpHandler);
     608             : 
     609           0 :         for (std::vector<DocumentElement *>::const_iterator pageMasterIter = mpImpl->mPageMasterStyles.begin();
     610           0 :                 pageMasterIter != mpImpl->mPageMasterStyles.end(); ++pageMasterIter)
     611             :         {
     612           0 :             (*pageMasterIter)->write(mpImpl->mpHandler);
     613             :         }
     614           0 :         mpImpl->mpHandler->endElement("office:master-styles");
     615             :     }
     616             : 
     617           0 :     if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_CONTENT_XML))
     618             :     {
     619           0 :         TagOpenElement("office:body").write(mpImpl->mpHandler);
     620             : 
     621           0 :         TagOpenElement("office:drawing").write(mpImpl->mpHandler);
     622             : 
     623           0 :         for (std::vector<DocumentElement *>::const_iterator bodyIter = mpImpl->mBodyElements.begin();
     624           0 :                 bodyIter != mpImpl->mBodyElements.end(); ++bodyIter)
     625             :         {
     626           0 :             (*bodyIter)->write(mpImpl->mpHandler);
     627             :         }
     628             : 
     629           0 :         mpImpl->mpHandler->endElement("office:drawing");
     630           0 :         mpImpl->mpHandler->endElement("office:body");
     631             :     }
     632             : 
     633             :     mpImpl->mpHandler->endElement(
     634             :         (mpImpl->mxStreamType == ODF_FLAT_XML) ? "office:document" : (
     635             :             (mpImpl->mxStreamType == ODF_CONTENT_XML) ? "office:document-content" : (
     636             :                 (mpImpl->mxStreamType == ODF_STYLES_XML) ? "office:document-styles" : (
     637             :                     (mpImpl->mxStreamType == ODF_SETTINGS_XML) ? "office:document-settings" : (
     638           0 :                         (mpImpl->mxStreamType == ODF_META_XML) ? "office:document-meta" : "office:document" )))));
     639             : 
     640           0 :     mpImpl->mpHandler->endDocument();
     641             : 
     642           0 :     if (mpImpl)
     643           0 :         delete mpImpl;
     644           0 : }
     645             : 
     646           0 : void OdgGenerator::startGraphics(const ::WPXPropertyList &propList)
     647             : {
     648           0 :     if (propList["svg:width"])
     649             :     {
     650           0 :         mpImpl->mfWidth = propList["svg:width"]->getDouble();
     651           0 :         mpImpl->mfMaxWidth = mpImpl->mfMaxWidth < mpImpl->mfWidth ? mpImpl->mfWidth : mpImpl->mfMaxWidth;
     652             :     }
     653             : 
     654           0 :     if (propList["svg:height"])
     655             :     {
     656           0 :         mpImpl->mfHeight = propList["svg:height"]->getDouble();
     657           0 :         mpImpl->mfMaxHeight = mpImpl->mfMaxHeight < mpImpl->mfHeight ? mpImpl->mfHeight : mpImpl->mfMaxHeight;
     658             :     }
     659             : 
     660           0 :     TagOpenElement *pStyleMasterPageOpenElement = new TagOpenElement("style:master-page");
     661             : 
     662           0 :     TagOpenElement *pDrawPageOpenElement = new TagOpenElement("draw:page");
     663             : 
     664           0 :     TagOpenElement *pStylePageLayoutOpenElement = new TagOpenElement("style:page-layout");
     665             : 
     666           0 :     WPXString sValue;
     667           0 :     sValue.sprintf("page%i", mpImpl->miPageIndex);
     668           0 :     pDrawPageOpenElement->addAttribute("draw:name", sValue);
     669             : #ifdef MULTIPAGE_WORKAROUND
     670           0 :     pStyleMasterPageOpenElement->addAttribute("style:page-layout-name", "PM0");
     671           0 :     pStylePageLayoutOpenElement->addAttribute("style:page-layout-name", "PM0");
     672             : #else
     673             :     sValue.sprintf("PM%i", mpImpl->miPageIndex);
     674             :     pStyleMasterPageOpenElement->addAttribute("style:page-layout-name", sValue);
     675             :     pStylePageLayoutOpenElement->addAttribute("style:name", sValue);
     676             : #endif
     677             : 
     678           0 :     mpImpl->mPageAutomaticStyles.push_back(pStylePageLayoutOpenElement);
     679             : 
     680           0 :     TagOpenElement *pStylePageLayoutPropertiesOpenElement = new TagOpenElement("style:page-layout-properties");
     681           0 :     pStylePageLayoutPropertiesOpenElement->addAttribute("fo:margin-top", "0in");
     682           0 :     pStylePageLayoutPropertiesOpenElement->addAttribute("fo:margin-bottom", "0in");
     683           0 :     pStylePageLayoutPropertiesOpenElement->addAttribute("fo:margin-left", "0in");
     684           0 :     pStylePageLayoutPropertiesOpenElement->addAttribute("fo:margin-right", "0in");
     685           0 :     sValue.sprintf("%s%s", doubleToString(mpImpl->mfWidth).cstr(), "in");
     686           0 :     pStylePageLayoutPropertiesOpenElement->addAttribute("fo:page-width", sValue);
     687           0 :     sValue.sprintf("%s%s", doubleToString(mpImpl->mfHeight).cstr(), "in");
     688           0 :     pStylePageLayoutPropertiesOpenElement->addAttribute("fo:page-height", sValue);
     689           0 :     pStylePageLayoutPropertiesOpenElement->addAttribute("style:print-orientation", "portrait");
     690           0 :     mpImpl->mPageAutomaticStyles.push_back(pStylePageLayoutPropertiesOpenElement);
     691             : 
     692           0 :     mpImpl->mPageAutomaticStyles.push_back(new TagCloseElement("style:page-layout-properties"));
     693             : 
     694           0 :     mpImpl->mPageAutomaticStyles.push_back(new TagCloseElement("style:page-layout"));
     695             : 
     696             : #ifdef MULTIPAGE_WORKAROUND
     697           0 :     pDrawPageOpenElement->addAttribute("draw:style-name", "dp1");
     698           0 :     pStyleMasterPageOpenElement->addAttribute("draw:style-name", "dp1");
     699             : #else
     700             :     sValue.sprintf("dp%i", mpImpl->miPageIndex);
     701             :     pDrawPageOpenElement->addAttribute("draw:style-name", sValue);
     702             :     pStyleMasterPageOpenElement->addAttribute("draw:style-name", sValue);
     703             : #endif
     704             : 
     705           0 :     TagOpenElement *pStyleStyleOpenElement = new TagOpenElement("style:style");
     706           0 :     pStyleStyleOpenElement->addAttribute("style:name", sValue);
     707           0 :     pStyleStyleOpenElement->addAttribute("style:family", "drawing-page");
     708           0 :     mpImpl->mPageAutomaticStyles.push_back(pStyleStyleOpenElement);
     709             : 
     710             : #ifdef MULTIPAGE_WORKAROUND
     711           0 :     pDrawPageOpenElement->addAttribute("draw:master-page-name", "Default");
     712           0 :     pStyleMasterPageOpenElement->addAttribute("style:name", "Default");
     713             : #else
     714             :     sValue.sprintf("Page%i", mpImpl->miPageIndex);
     715             :     pDrawPageOpenElement->addAttribute("draw:master-page-name", sValue);
     716             :     pStyleMasterPageOpenElement->addAttribute("style:name", sValue);
     717             : #endif
     718             : 
     719           0 :     mpImpl->mBodyElements.push_back(pDrawPageOpenElement);
     720             : 
     721           0 :     mpImpl->mPageMasterStyles.push_back(pStyleMasterPageOpenElement);
     722           0 :     mpImpl->mPageMasterStyles.push_back(new TagCloseElement("style:master-page"));
     723             : 
     724             : 
     725           0 :     TagOpenElement *pStyleDrawingPagePropertiesOpenElement = new TagOpenElement("style:drawing-page-properties");
     726           0 :     pStyleDrawingPagePropertiesOpenElement->addAttribute("draw:fill", "none");
     727           0 :     mpImpl->mPageAutomaticStyles.push_back(pStyleDrawingPagePropertiesOpenElement);
     728             : 
     729           0 :     mpImpl->mPageAutomaticStyles.push_back(new TagCloseElement("style:drawing-page-properties"));
     730             : 
     731           0 :     mpImpl->mPageAutomaticStyles.push_back(new TagCloseElement("style:style"));
     732           0 : }
     733             : 
     734           0 : void OdgGenerator::endGraphics()
     735             : {
     736           0 :     mpImpl->mBodyElements.push_back(new TagCloseElement("draw:page"));
     737           0 :     mpImpl->miPageIndex++;
     738           0 : }
     739             : 
     740           0 : void OdgGenerator::setStyle(const ::WPXPropertyList &propList, const ::WPXPropertyListVector &gradient)
     741             : {
     742           0 :     mpImpl->mxStyle.clear();
     743           0 :     mpImpl->mxStyle = propList;
     744           0 :     mpImpl->mxGradient = gradient;
     745           0 : }
     746             : 
     747           0 : void OdgGenerator::startLayer(const ::WPXPropertyList & /* propList */)
     748             : {
     749           0 :     mpImpl->mBodyElements.push_back(new TagOpenElement("draw:g"));
     750           0 : }
     751             : 
     752           0 : void OdgGenerator::endLayer()
     753             : {
     754           0 :     mpImpl->mBodyElements.push_back(new TagCloseElement("draw:g"));
     755           0 : }
     756             : 
     757           0 : void OdgGenerator::drawRectangle(const ::WPXPropertyList &propList)
     758             : {
     759           0 :     mpImpl->_writeGraphicsStyle();
     760           0 :     TagOpenElement *pDrawRectElement = new TagOpenElement("draw:rect");
     761           0 :     WPXString sValue;
     762           0 :     sValue.sprintf("gr%i", mpImpl->miGraphicsStyleIndex-1);
     763           0 :     pDrawRectElement->addAttribute("draw:style-name", sValue);
     764           0 :     pDrawRectElement->addAttribute("svg:x", propList["svg:x"]->getStr());
     765           0 :     pDrawRectElement->addAttribute("svg:y", propList["svg:y"]->getStr());
     766           0 :     pDrawRectElement->addAttribute("svg:width", propList["svg:width"]->getStr());
     767           0 :     pDrawRectElement->addAttribute("svg:height", propList["svg:height"]->getStr());
     768             :     // FIXME: what to do when rx != ry ?
     769           0 :     if (propList["svg:rx"])
     770           0 :         pDrawRectElement->addAttribute("draw:corner-radius", propList["svg:rx"]->getStr());
     771             :     else
     772           0 :         pDrawRectElement->addAttribute("draw:corner-radius", "0.0000in");
     773           0 :     mpImpl->mBodyElements.push_back(pDrawRectElement);
     774           0 :     mpImpl->mBodyElements.push_back(new TagCloseElement("draw:rect"));
     775           0 : }
     776             : 
     777           0 : void OdgGenerator::drawEllipse(const ::WPXPropertyList &propList)
     778             : {
     779           0 :     mpImpl->_writeGraphicsStyle();
     780           0 :     TagOpenElement *pDrawEllipseElement = new TagOpenElement("draw:ellipse");
     781           0 :     WPXString sValue;
     782           0 :     sValue.sprintf("gr%i", mpImpl->miGraphicsStyleIndex-1);
     783           0 :     pDrawEllipseElement->addAttribute("draw:style-name", sValue);
     784           0 :     sValue = doubleToString(2 * propList["svg:rx"]->getDouble());
     785           0 :     sValue.append("in");
     786           0 :     pDrawEllipseElement->addAttribute("svg:width", sValue);
     787           0 :     sValue = doubleToString(2 * propList["svg:ry"]->getDouble());
     788           0 :     sValue.append("in");
     789           0 :     pDrawEllipseElement->addAttribute("svg:height", sValue);
     790           0 :     if (propList["libwpg:rotate"] && propList["libwpg:rotate"]->getDouble() != 0.0)
     791             :     {
     792           0 :         double rotation = propList["libwpg:rotate"]->getDouble();
     793           0 :         while(rotation < -180)
     794           0 :             rotation += 360;
     795           0 :         while(rotation > 180)
     796           0 :             rotation -= 360;
     797           0 :         double radrotation = rotation*M_PI/180.0;
     798           0 :         double deltax = sqrt(pow(propList["svg:rx"]->getDouble(), 2.0)
     799           0 :                              + pow(propList["svg:ry"]->getDouble(), 2.0))*cos(atan(propList["svg:ry"]->getDouble()/propList["svg:rx"]->getDouble())
     800           0 :                                      - radrotation ) - propList["svg:rx"]->getDouble();
     801           0 :         double deltay = sqrt(pow(propList["svg:rx"]->getDouble(), 2.0)
     802           0 :                              + pow(propList["svg:ry"]->getDouble(), 2.0))*sin(atan(propList["svg:ry"]->getDouble()/propList["svg:rx"]->getDouble())
     803           0 :                                      - radrotation ) - propList["svg:ry"]->getDouble();
     804           0 :         sValue = "rotate(";
     805           0 :         sValue.append(doubleToString(radrotation));
     806           0 :         sValue.append(") ");
     807           0 :         sValue.append("translate(");
     808           0 :         sValue.append(doubleToString(propList["svg:cx"]->getDouble() - propList["svg:rx"]->getDouble() - deltax));
     809           0 :         sValue.append("in, ");
     810           0 :         sValue.append(doubleToString(propList["svg:cy"]->getDouble() - propList["svg:ry"]->getDouble() - deltay));
     811           0 :         sValue.append("in)");
     812           0 :         pDrawEllipseElement->addAttribute("draw:transform", sValue);
     813             :     }
     814             :     else
     815             :     {
     816           0 :         sValue = doubleToString(propList["svg:cx"]->getDouble()-propList["svg:rx"]->getDouble());
     817           0 :         sValue.append("in");
     818           0 :         pDrawEllipseElement->addAttribute("svg:x", sValue);
     819           0 :         sValue = doubleToString(propList["svg:cy"]->getDouble()-propList["svg:ry"]->getDouble());
     820           0 :         sValue.append("in");
     821           0 :         pDrawEllipseElement->addAttribute("svg:y", sValue);
     822             :     }
     823           0 :     mpImpl->mBodyElements.push_back(pDrawEllipseElement);
     824           0 :     mpImpl->mBodyElements.push_back(new TagCloseElement("draw:ellipse"));
     825           0 : }
     826             : 
     827           0 : void OdgGenerator::drawPolyline(const ::WPXPropertyListVector &vertices)
     828             : {
     829           0 :     mpImpl->_drawPolySomething(vertices, false);
     830           0 : }
     831             : 
     832           0 : void OdgGenerator::drawPolygon(const ::WPXPropertyListVector &vertices)
     833             : {
     834           0 :     mpImpl->_drawPolySomething(vertices, true);
     835           0 : }
     836             : 
     837           0 : void OdgGeneratorPrivate::_drawPolySomething(const ::WPXPropertyListVector &vertices, bool isClosed)
     838             : {
     839           0 :     if(vertices.count() < 2)
     840           0 :         return;
     841             : 
     842           0 :     if(vertices.count() == 2)
     843             :     {
     844           0 :         _writeGraphicsStyle();
     845           0 :         TagOpenElement *pDrawLineElement = new TagOpenElement("draw:line");
     846           0 :         WPXString sValue;
     847           0 :         sValue.sprintf("gr%i", miGraphicsStyleIndex-1);
     848           0 :         pDrawLineElement->addAttribute("draw:style-name", sValue);
     849           0 :         pDrawLineElement->addAttribute("draw:layer", "layout");
     850           0 :         pDrawLineElement->addAttribute("svg:x1", vertices[0]["svg:x"]->getStr());
     851           0 :         pDrawLineElement->addAttribute("svg:y1", vertices[0]["svg:y"]->getStr());
     852           0 :         pDrawLineElement->addAttribute("svg:x2", vertices[1]["svg:x"]->getStr());
     853           0 :         pDrawLineElement->addAttribute("svg:y2", vertices[1]["svg:y"]->getStr());
     854           0 :         mBodyElements.push_back(pDrawLineElement);
     855           0 :         mBodyElements.push_back(new TagCloseElement("draw:line"));
     856             :     }
     857             :     else
     858             :     {
     859           0 :         ::WPXPropertyListVector path;
     860           0 :         ::WPXPropertyList element;
     861             : 
     862           0 :         for (unsigned long ii = 0; ii < vertices.count(); ++ii)
     863             :         {
     864           0 :             element = vertices[ii];
     865           0 :             if (ii == 0)
     866           0 :                 element.insert("libwpg:path-action", "M");
     867             :             else
     868           0 :                 element.insert("libwpg:path-action", "L");
     869           0 :             path.append(element);
     870           0 :             element.clear();
     871             :         }
     872           0 :         if (isClosed)
     873             :         {
     874           0 :             element.insert("libwpg:path-action", "Z");
     875           0 :             path.append(element);
     876             :         }
     877           0 :         _drawPath(path);
     878             :     }
     879             : }
     880             : 
     881           0 : void OdgGeneratorPrivate::_drawPath(const WPXPropertyListVector &path)
     882             : {
     883           0 :     if(path.count() == 0)
     884             :         return;
     885             :     // This must be a mistake and we do not want to crash lower
     886           0 :     if(path[0]["libwpg:path-action"]->getStr() == "Z")
     887             :         return;
     888             : 
     889             :     // try to find the bounding box
     890             :     // this is simple convex hull technique, the bounding box might not be
     891             :     // accurate but that should be enough for this purpose
     892           0 :     bool isFirstPoint = true;
     893             : 
     894           0 :     double px = 0.0, py = 0.0, qx = 0.0, qy = 0.0;
     895           0 :     double lastX = 0.0;
     896           0 :     double lastY = 0.0;
     897             : 
     898           0 :     for(unsigned k = 0; k < path.count(); ++k)
     899             :     {
     900           0 :         if (!path[k]["svg:x"] || !path[k]["svg:y"])
     901           0 :             continue;
     902           0 :         if (isFirstPoint)
     903             :         {
     904           0 :             px = path[k]["svg:x"]->getDouble();
     905           0 :             py = path[k]["svg:y"]->getDouble();
     906           0 :             qx = px;
     907           0 :             qy = py;
     908           0 :             lastX = px;
     909           0 :             lastY = py;
     910           0 :             isFirstPoint = false;
     911             :         }
     912           0 :         px = (px > path[k]["svg:x"]->getDouble()) ? path[k]["svg:x"]->getDouble() : px;
     913           0 :         py = (py > path[k]["svg:y"]->getDouble()) ? path[k]["svg:y"]->getDouble() : py;
     914           0 :         qx = (qx < path[k]["svg:x"]->getDouble()) ? path[k]["svg:x"]->getDouble() : qx;
     915           0 :         qy = (qy < path[k]["svg:y"]->getDouble()) ? path[k]["svg:y"]->getDouble() : qy;
     916             : 
     917             :         double xmin, xmax, ymin, ymax;
     918             : 
     919           0 :         if(path[k]["libwpg:path-action"]->getStr() == "C")
     920             :         {
     921           0 :             getCubicBezierBBox(lastX, lastY, path[k]["svg:x1"]->getDouble(), path[k]["svg:y1"]->getDouble(),
     922           0 :                                path[k]["svg:x2"]->getDouble(), path[k]["svg:y2"]->getDouble(),
     923           0 :                                path[k]["svg:x"]->getDouble(), path[k]["svg:y"]->getDouble(), xmin, ymin, xmax, ymax);
     924             : 
     925           0 :             px = (px > xmin ? xmin : px);
     926           0 :             py = (py > ymin ? ymin : py);
     927           0 :             qx = (qx < xmax ? xmax : qx);
     928           0 :             qy = (qy < ymax ? ymax : qy);
     929             :         }
     930           0 :         if(path[k]["libwpg:path-action"]->getStr() == "Q")
     931             :         {
     932           0 :             getQuadraticBezierBBox(lastX, lastY, path[k]["svg:x1"]->getDouble(), path[k]["svg:y1"]->getDouble(),
     933           0 :                                    path[k]["svg:x"]->getDouble(), path[k]["svg:y"]->getDouble(), xmin, ymin, xmax, ymax);
     934             : 
     935           0 :             px = (px > xmin ? xmin : px);
     936           0 :             py = (py > ymin ? ymin : py);
     937           0 :             qx = (qx < xmax ? xmax : qx);
     938           0 :             qy = (qy < ymax ? ymax : qy);
     939             :         }
     940           0 :         if(path[k]["libwpg:path-action"]->getStr() == "A")
     941             :         {
     942           0 :             getEllipticalArcBBox(lastX, lastY, path[k]["svg:rx"]->getDouble(), path[k]["svg:ry"]->getDouble(),
     943           0 :                                  path[k]["libwpg:rotate"] ? path[k]["libwpg:rotate"]->getDouble() : 0.0,
     944           0 :                                  path[k]["libwpg:large-arc"] ? path[k]["libwpg:large-arc"]->getInt() : 1,
     945           0 :                                  path[k]["libwpg:sweep"] ? path[k]["libwpg:sweep"]->getInt() : 1,
     946           0 :                                  path[k]["svg:x"]->getDouble(), path[k]["svg:y"]->getDouble(), xmin, ymin, xmax, ymax);
     947             : 
     948           0 :             px = (px > xmin ? xmin : px);
     949           0 :             py = (py > ymin ? ymin : py);
     950           0 :             qx = (qx < xmax ? xmax : qx);
     951           0 :             qy = (qy < ymax ? ymax : qy);
     952             :         }
     953           0 :         lastX = path[k]["svg:x"]->getDouble();
     954           0 :         lastY = path[k]["svg:y"]->getDouble();
     955             :     }
     956             : 
     957             : 
     958           0 :     WPXString sValue;
     959           0 :     _writeGraphicsStyle();
     960           0 :     TagOpenElement *pDrawPathElement = new TagOpenElement("draw:path");
     961           0 :     sValue.sprintf("gr%i", miGraphicsStyleIndex-1);
     962           0 :     pDrawPathElement->addAttribute("draw:style-name", sValue);
     963           0 :     pDrawPathElement->addAttribute("draw:layer", "layout");
     964           0 :     sValue = doubleToString(px);
     965           0 :     sValue.append("in");
     966           0 :     pDrawPathElement->addAttribute("svg:x", sValue);
     967           0 :     sValue = doubleToString(py);
     968           0 :     sValue.append("in");
     969           0 :     pDrawPathElement->addAttribute("svg:y", sValue);
     970           0 :     sValue = doubleToString((qx - px));
     971           0 :     sValue.append("in");
     972           0 :     pDrawPathElement->addAttribute("svg:width", sValue);
     973           0 :     sValue = doubleToString((qy - py));
     974           0 :     sValue.append("in");
     975           0 :     pDrawPathElement->addAttribute("svg:height", sValue);
     976           0 :     sValue.sprintf("%i %i %i %i", 0, 0, (unsigned)(2540*(qx - px)), (unsigned)(2540*(qy - py)));
     977           0 :     pDrawPathElement->addAttribute("svg:viewBox", sValue);
     978             : 
     979           0 :     sValue.clear();
     980           0 :     for(unsigned i = 0; i < path.count(); ++i)
     981             :     {
     982           0 :         WPXString sElement;
     983           0 :         if (path[i]["libwpg:path-action"]->getStr() == "M")
     984             :         {
     985             :             // 2540 is 2.54*1000, 2.54 in = 1 inch
     986           0 :             sElement.sprintf("M%i %i", (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540),
     987           0 :                              (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540));
     988           0 :             sValue.append(sElement);
     989             :         }
     990           0 :         else if (path[i]["libwpg:path-action"]->getStr() == "L")
     991             :         {
     992           0 :             sElement.sprintf("L%i %i", (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540),
     993           0 :                              (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540));
     994           0 :             sValue.append(sElement);
     995             :         }
     996           0 :         else if (path[i]["libwpg:path-action"]->getStr() == "C")
     997             :         {
     998           0 :             sElement.sprintf("C%i %i %i %i %i %i", (unsigned)((path[i]["svg:x1"]->getDouble()-px)*2540),
     999           0 :                              (unsigned)((path[i]["svg:y1"]->getDouble()-py)*2540), (unsigned)((path[i]["svg:x2"]->getDouble()-px)*2540),
    1000           0 :                              (unsigned)((path[i]["svg:y2"]->getDouble()-py)*2540), (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540),
    1001           0 :                              (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540));
    1002           0 :             sValue.append(sElement);
    1003             :         }
    1004           0 :         else if (path[i]["libwpg:path-action"]->getStr() == "Q")
    1005             :         {
    1006           0 :             sElement.sprintf("Q%i %i %i %i", (unsigned)((path[i]["svg:x1"]->getDouble()-px)*2540),
    1007           0 :                              (unsigned)((path[i]["svg:y1"]->getDouble()-py)*2540), (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540),
    1008           0 :                              (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540));
    1009           0 :             sValue.append(sElement);
    1010             :         }
    1011           0 :         else if (path[i]["libwpg:path-action"]->getStr() == "A")
    1012             :         {
    1013           0 :             sElement.sprintf("A%i %i %i %i %i %i %i", (unsigned)((path[i]["svg:rx"]->getDouble())*2540),
    1014           0 :                              (unsigned)((path[i]["svg:ry"]->getDouble())*2540), (path[i]["libwpg:rotate"] ? path[i]["libwpg:rotate"]->getInt() : 0),
    1015           0 :                              (path[i]["libwpg:large-arc"] ? path[i]["libwpg:large-arc"]->getInt() : 1),
    1016           0 :                              (path[i]["libwpg:sweep"] ? path[i]["libwpg:sweep"]->getInt() : 1),
    1017           0 :                              (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540), (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540));
    1018           0 :             sValue.append(sElement);
    1019             :         }
    1020           0 :         else if (path[i]["libwpg:path-action"]->getStr() == "Z")
    1021           0 :             sValue.append(" Z");
    1022           0 :     }
    1023           0 :     pDrawPathElement->addAttribute("svg:d", sValue);
    1024           0 :     mBodyElements.push_back(pDrawPathElement);
    1025           0 :     mBodyElements.push_back(new TagCloseElement("draw:path"));
    1026             : }
    1027             : 
    1028           0 : void OdgGenerator::drawPath(const WPXPropertyListVector &path)
    1029             : {
    1030           0 :     mpImpl->_drawPath(path);
    1031           0 : }
    1032             : 
    1033           0 : void OdgGenerator::drawGraphicObject(const ::WPXPropertyList &propList, const ::WPXBinaryData &binaryData)
    1034             : {
    1035           0 :     if (!propList["libwpg:mime-type"] || propList["libwpg:mime-type"]->getStr().len() <= 0)
    1036             :         return;
    1037           0 :     if (!propList["svg:x"] || !propList["svg:y"] || !propList["svg:width"] || !propList["svg:height"])
    1038             :         return;
    1039             : 
    1040           0 :     bool flipX(propList["draw:mirror-horizontal"] && propList["draw:mirror-horizontal"]->getInt());
    1041           0 :     bool flipY(propList["draw:mirror-vertical"] && propList["draw:mirror-vertical"]->getInt());
    1042           0 :     if ((flipX && !flipY) || (!flipX && flipY))
    1043           0 :         mpImpl->mxStyle.insert("style:mirror", "horizontal");
    1044             :     else
    1045           0 :         mpImpl->mxStyle.insert("style:mirror", "none");
    1046           0 :     if (propList["draw:color-mode"])
    1047           0 :         mpImpl->mxStyle.insert("draw:color-mode", propList["draw:color-mode"]->getStr());
    1048           0 :     if (propList["draw:luminance"])
    1049           0 :         mpImpl->mxStyle.insert("draw:luminance", propList["draw:luminance"]->getStr());
    1050           0 :     if (propList["draw:contrast"])
    1051           0 :         mpImpl->mxStyle.insert("draw:contrast", propList["draw:contrast"]->getStr());
    1052           0 :     if (propList["draw:gamma"])
    1053           0 :         mpImpl->mxStyle.insert("draw:gamma", propList["draw:gamma"]->getStr());
    1054           0 :     if (propList["draw:red"])
    1055           0 :         mpImpl->mxStyle.insert("draw:red", propList["draw:red"]->getStr());
    1056           0 :     if (propList["draw:green"])
    1057           0 :         mpImpl->mxStyle.insert("draw:green", propList["draw:green"]->getStr());
    1058           0 :     if (propList["draw:blue"])
    1059           0 :         mpImpl->mxStyle.insert("draw:blue", propList["draw:blue"]->getStr());
    1060             : 
    1061             : 
    1062           0 :     mpImpl->_writeGraphicsStyle();
    1063             : 
    1064           0 :     double x = propList["svg:x"]->getDouble();
    1065           0 :     double y = propList["svg:y"]->getDouble();
    1066           0 :     double height = propList["svg:height"]->getDouble();
    1067           0 :     double width = propList["svg:width"]->getDouble();
    1068             : 
    1069           0 :     if (flipY)
    1070             :     {
    1071           0 :         x += width;
    1072           0 :         y += height;
    1073           0 :         width *= -1.0;
    1074           0 :         height *= -1.0;
    1075             :     }
    1076             : 
    1077           0 :     double angle(propList["libwpg:rotate"] ? - M_PI * propList["libwpg:rotate"]->getDouble() / 180.0 : 0.0);
    1078           0 :     if (angle != 0.0)
    1079             :     {
    1080           0 :         double deltax((width*cos(angle)+height*sin(angle)-width)/2.0);
    1081           0 :         double deltay((-width*sin(angle)+height*cos(angle)-height)/2.0);
    1082           0 :         x -= deltax;
    1083           0 :         y -= deltay;
    1084             :     }
    1085             : 
    1086           0 :     WPXPropertyList framePropList;
    1087             : 
    1088           0 :     framePropList.insert("svg:x", x);
    1089           0 :     framePropList.insert("svg:y", y);
    1090           0 :     framePropList.insert("svg:height", height);
    1091           0 :     framePropList.insert("svg:width", width);
    1092             : 
    1093           0 :     TagOpenElement *pDrawFrameElement = new TagOpenElement("draw:frame");
    1094             : 
    1095           0 :     WPXString sValue;
    1096           0 :     sValue.sprintf("gr%i", mpImpl->miGraphicsStyleIndex-1);
    1097           0 :     pDrawFrameElement->addAttribute("draw:style-name", sValue);
    1098             : 
    1099           0 :     pDrawFrameElement->addAttribute("svg:height", framePropList["svg:height"]->getStr());
    1100           0 :     pDrawFrameElement->addAttribute("svg:width", framePropList["svg:width"]->getStr());
    1101             : 
    1102           0 :     if (angle != 0.0)
    1103             :     {
    1104           0 :         framePropList.insert("libwpg:rotate", angle, WPX_GENERIC);
    1105             :         sValue.sprintf("rotate (%s) translate(%s, %s)",
    1106           0 :                        framePropList["libwpg:rotate"]->getStr().cstr(),
    1107           0 :                        framePropList["svg:x"]->getStr().cstr(),
    1108           0 :                        framePropList["svg:y"]->getStr().cstr());
    1109           0 :         pDrawFrameElement->addAttribute("draw:transform", sValue);
    1110             :     }
    1111             :     else
    1112             :     {
    1113           0 :         pDrawFrameElement->addAttribute("svg:x", framePropList["svg:x"]->getStr());
    1114           0 :         pDrawFrameElement->addAttribute("svg:y", framePropList["svg:y"]->getStr());
    1115             :     }
    1116           0 :     mpImpl->mBodyElements.push_back(pDrawFrameElement);
    1117             : 
    1118           0 :     if (propList["libwpg:mime-type"]->getStr() == "object/ole")
    1119           0 :         mpImpl->mBodyElements.push_back(new TagOpenElement("draw:object-ole"));
    1120             :     else
    1121           0 :         mpImpl->mBodyElements.push_back(new TagOpenElement("draw:image"));
    1122             : 
    1123           0 :     mpImpl->mBodyElements.push_back(new TagOpenElement("office:binary-data"));
    1124             : 
    1125           0 :     ::WPXString base64Binary = binaryData.getBase64Data();
    1126           0 :     mpImpl->mBodyElements.push_back(new CharDataElement(base64Binary.cstr()));
    1127             : 
    1128           0 :     mpImpl->mBodyElements.push_back(new TagCloseElement("office:binary-data"));
    1129             : 
    1130           0 :     if (propList["libwpg:mime-type"]->getStr() == "object/ole")
    1131           0 :         mpImpl->mBodyElements.push_back(new TagCloseElement("draw:object-ole"));
    1132             :     else
    1133           0 :         mpImpl->mBodyElements.push_back(new TagCloseElement("draw:image"));
    1134             : 
    1135           0 :     mpImpl->mBodyElements.push_back(new TagCloseElement("draw:frame"));
    1136             : }
    1137             : 
    1138           0 : void OdgGeneratorPrivate::_writeGraphicsStyle()
    1139             : {
    1140           0 :     bool bUseOpacityGradient = false;
    1141             : 
    1142           0 :     if (mxStyle["draw:stroke"] && mxStyle["draw:stroke"]->getStr() == "dash")
    1143             :     {
    1144           0 :         TagOpenElement *pDrawStrokeDashElement = new TagOpenElement("draw:stroke-dash");
    1145           0 :         WPXString sValue;
    1146           0 :         sValue.sprintf("Dash_%i", miDashIndex++);
    1147           0 :         pDrawStrokeDashElement->addAttribute("draw:name", sValue);
    1148           0 :         if (mxStyle["svg:stoke-linecap"])
    1149           0 :             pDrawStrokeDashElement->addAttribute("draw:style", mxStyle["svg:stroke-linecap"]->getStr());
    1150             :         else
    1151           0 :             pDrawStrokeDashElement->addAttribute("draw:style", "rect");
    1152           0 :         if (mxStyle["draw:distance"])
    1153           0 :             pDrawStrokeDashElement->addAttribute("draw:distance", mxStyle["draw:distance"]->getStr());
    1154           0 :         if (mxStyle["draw:dots1"])
    1155           0 :             pDrawStrokeDashElement->addAttribute("draw:dots1", mxStyle["draw:dots1"]->getStr());
    1156           0 :         if (mxStyle["draw:dots1-length"])
    1157           0 :             pDrawStrokeDashElement->addAttribute("draw:dots1-length", mxStyle["draw:dots1-length"]->getStr());
    1158           0 :         if (mxStyle["draw:dots2"])
    1159           0 :             pDrawStrokeDashElement->addAttribute("draw:dots2", mxStyle["draw:dots2"]->getStr());
    1160           0 :         if (mxStyle["draw:dots2-length"])
    1161           0 :             pDrawStrokeDashElement->addAttribute("draw:dots2-length", mxStyle["draw:dots2-length"]->getStr());
    1162           0 :         mGraphicsStrokeDashStyles.push_back(pDrawStrokeDashElement);
    1163           0 :         mGraphicsStrokeDashStyles.push_back(new TagCloseElement("draw:stroke-dash"));
    1164             :     }
    1165             : 
    1166           0 :     if (mxStyle["draw:marker-start-path"])
    1167             :     {
    1168           0 :         WPXString sValue;
    1169           0 :         TagOpenElement *pDrawMarkerElement = new TagOpenElement("draw:marker");
    1170           0 :         sValue.sprintf("StartMarker_%i", miStartMarkerIndex);
    1171           0 :         pDrawMarkerElement->addAttribute("draw:name", sValue);
    1172           0 :         if (mxStyle["draw:marker-start-viewbox"])
    1173           0 :             pDrawMarkerElement->addAttribute("svg:viewBox", mxStyle["draw:marker-start-viewbox"]->getStr());
    1174           0 :         pDrawMarkerElement->addAttribute("svg:d", mxStyle["draw:marker-start-path"]->getStr());
    1175           0 :         mGraphicsMarkerStyles.push_back(pDrawMarkerElement);
    1176           0 :         mGraphicsMarkerStyles.push_back(new TagCloseElement("draw:marker"));
    1177             :     }
    1178           0 :     if(mxStyle["draw:marker-end-path"])
    1179             :     {
    1180           0 :         WPXString sValue;
    1181           0 :         TagOpenElement *pDrawMarkerElement = new TagOpenElement("draw:marker");
    1182           0 :         sValue.sprintf("EndMarker_%i", miEndMarkerIndex);
    1183           0 :         pDrawMarkerElement->addAttribute("draw:name", sValue);
    1184           0 :         if (mxStyle["draw:marker-end-viewbox"])
    1185           0 :             pDrawMarkerElement->addAttribute("svg:viewBox", mxStyle["draw:marker-end-viewbox"]->getStr());
    1186           0 :         pDrawMarkerElement->addAttribute("svg:d", mxStyle["draw:marker-end-path"]->getStr());
    1187           0 :         mGraphicsMarkerStyles.push_back(pDrawMarkerElement);
    1188           0 :         mGraphicsMarkerStyles.push_back(new TagCloseElement("draw:marker"));
    1189             :     }
    1190             : 
    1191           0 :     if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "gradient")
    1192             :     {
    1193           0 :         TagOpenElement *pDrawGradientElement = new TagOpenElement("draw:gradient");
    1194           0 :         TagOpenElement *pDrawOpacityElement = new TagOpenElement("draw:opacity");
    1195           0 :         if (mxStyle["draw:style"])
    1196             :         {
    1197           0 :             pDrawGradientElement->addAttribute("draw:style", mxStyle["draw:style"]->getStr());
    1198           0 :             pDrawOpacityElement->addAttribute("draw:style", mxStyle["draw:style"]->getStr());
    1199             :         }
    1200             :         else
    1201             :         {
    1202           0 :             pDrawGradientElement->addAttribute("draw:style", "linear");
    1203           0 :             pDrawOpacityElement->addAttribute("draw:style", "linear");
    1204             :         }
    1205           0 :         WPXString sValue;
    1206           0 :         sValue.sprintf("Gradient_%i", miGradientIndex);
    1207           0 :         pDrawGradientElement->addAttribute("draw:name", sValue);
    1208           0 :         sValue.sprintf("Transparency_%i", miGradientIndex++);
    1209           0 :         pDrawOpacityElement->addAttribute("draw:name", sValue);
    1210             : 
    1211             :         // ODG angle unit is 0.1 degree
    1212           0 :         double angle = mxStyle["draw:angle"] ? mxStyle["draw:angle"]->getDouble() : 0.0;
    1213           0 :         while(angle < 0)
    1214           0 :             angle += 360;
    1215           0 :         while(angle > 360)
    1216           0 :             angle -= 360;
    1217           0 :         sValue.sprintf("%i", (unsigned)(angle*10));
    1218           0 :         pDrawGradientElement->addAttribute("draw:angle", sValue);
    1219           0 :         pDrawOpacityElement->addAttribute("draw:angle", sValue);
    1220             : 
    1221           0 :         if (!mxGradient.count())
    1222             :         {
    1223           0 :             if (mxStyle["draw:start-color"])
    1224           0 :                 pDrawGradientElement->addAttribute("draw:start-color", mxStyle["draw:start-color"]->getStr());
    1225           0 :             if (mxStyle["draw:end-color"])
    1226           0 :                 pDrawGradientElement->addAttribute("draw:end-color", mxStyle["draw:end-color"]->getStr());
    1227             : 
    1228           0 :             if (mxStyle["draw:border"])
    1229             :             {
    1230           0 :                 pDrawGradientElement->addAttribute("draw:border", mxStyle["draw:border"]->getStr());
    1231           0 :                 pDrawOpacityElement->addAttribute("draw:border", mxStyle["draw:border"]->getStr());
    1232             :             }
    1233             :             else
    1234             :             {
    1235           0 :                 pDrawGradientElement->addAttribute("draw:border", "0%");
    1236           0 :                 pDrawOpacityElement->addAttribute("draw:border", "0%");
    1237             :             }
    1238             : 
    1239           0 :             if (mxStyle["svg:cx"])
    1240             :             {
    1241           0 :                 pDrawGradientElement->addAttribute("draw:cx", mxStyle["svg:cx"]->getStr());
    1242           0 :                 pDrawOpacityElement->addAttribute("draw:cx", mxStyle["svg:cx"]->getStr());
    1243             :             }
    1244           0 :             else if (mxStyle["draw:cx"])
    1245             :             {
    1246           0 :                 pDrawGradientElement->addAttribute("draw:cx", mxStyle["draw:cx"]->getStr());
    1247           0 :                 pDrawOpacityElement->addAttribute("draw:cx", mxStyle["draw:cx"]->getStr());
    1248             :             }
    1249             : 
    1250           0 :             if (mxStyle["svg:cy"])
    1251             :             {
    1252           0 :                 pDrawGradientElement->addAttribute("draw:cy", mxStyle["svg:cy"]->getStr());
    1253           0 :                 pDrawOpacityElement->addAttribute("draw:cy", mxStyle["svg:cy"]->getStr());
    1254             :             }
    1255           0 :             else if (mxStyle["draw:cx"])
    1256             :             {
    1257           0 :                 pDrawGradientElement->addAttribute("draw:cx", mxStyle["svg:cx"]->getStr());
    1258           0 :                 pDrawOpacityElement->addAttribute("draw:cx", mxStyle["svg:cx"]->getStr());
    1259             :             }
    1260             : 
    1261           0 :             if (mxStyle["draw:start-intensity"])
    1262           0 :                 pDrawGradientElement->addAttribute("draw:start-intensity", mxStyle["draw:start-intensity"]->getStr());
    1263             :             else
    1264           0 :                 pDrawGradientElement->addAttribute("draw:start-intensity", "100%");
    1265             : 
    1266           0 :             if (mxStyle["draw:end-intensity"])
    1267           0 :                 pDrawGradientElement->addAttribute("draw:end-intensity", mxStyle["draw:end-intensity"]->getStr());
    1268             :             else
    1269           0 :                 pDrawGradientElement->addAttribute("draw:end-intensity", "100%");
    1270             : 
    1271           0 :             if (mxStyle["libwpg:start-opacity"])
    1272           0 :                 pDrawOpacityElement->addAttribute("draw:start", mxStyle["libwpg:start-opacity"]->getStr());
    1273             :             else
    1274           0 :                 pDrawOpacityElement->addAttribute("draw:start", "100%");
    1275             : 
    1276           0 :             if (mxStyle["libwpg:end-opacity"])
    1277           0 :                 pDrawOpacityElement->addAttribute("draw:end", mxStyle["libwpg:end-opacity"]->getStr());
    1278             :             else
    1279           0 :                 pDrawOpacityElement->addAttribute("draw:end", "100%");
    1280             : 
    1281           0 :             mGraphicsGradientStyles.push_back(pDrawGradientElement);
    1282           0 :             mGraphicsGradientStyles.push_back(new TagCloseElement("draw:gradient"));
    1283             : 
    1284             :             // Work around a mess in LibreOffice where both opacities of 100% are interpreted as complete transparency
    1285             :             // Nevertheless, when one is different, immediately, they are interpreted correctly
    1286           0 :             if (mxStyle["libwpg:start-opacity"] && mxStyle["libwpg:end-opacity"]
    1287           0 :                     && (mxStyle["libwpg:start-opacity"]->getDouble() != 1.0 || mxStyle["libwpg:end-opacity"]->getDouble() != 1.0))
    1288             :             {
    1289           0 :                 bUseOpacityGradient = true;
    1290           0 :                 mGraphicsGradientStyles.push_back(pDrawOpacityElement);
    1291           0 :                 mGraphicsGradientStyles.push_back(new TagCloseElement("draw:opacity"));
    1292             :             }
    1293             :         }
    1294           0 :         else if(mxGradient.count() >= 2)
    1295             :         {
    1296           0 :             sValue.sprintf("%i", (unsigned)(angle*10));
    1297           0 :             pDrawGradientElement->addAttribute("draw:angle", sValue);
    1298             : 
    1299           0 :             pDrawGradientElement->addAttribute("draw:start-color", mxGradient[1]["svg:stop-color"]->getStr());
    1300           0 :             pDrawGradientElement->addAttribute("draw:end-color", mxGradient[0]["svg:stop-color"]->getStr());
    1301           0 :             if (mxStyle["svg:cx"])
    1302           0 :                 pDrawGradientElement->addAttribute("draw:cx", mxStyle["svg:cx"]->getStr());
    1303           0 :             if (mxStyle["svg:cy"])
    1304           0 :                 pDrawGradientElement->addAttribute("draw:cy", mxStyle["svg:cy"]->getStr());
    1305           0 :             if (mxGradient[1]["svg:stop-opacity"])
    1306             :             {
    1307           0 :                 pDrawOpacityElement->addAttribute("draw:start", mxGradient[1]["svg:stop-opacity"]->getStr());
    1308           0 :                 bUseOpacityGradient = true;
    1309             :             }
    1310             :             else
    1311           0 :                 pDrawOpacityElement->addAttribute("draw:start", "100%");
    1312           0 :             if (mxGradient[0]["svg:stop-opacity"])
    1313             :             {
    1314           0 :                 pDrawOpacityElement->addAttribute("draw:end", mxGradient[0]["svg:stop-opacity"]->getStr());
    1315           0 :                 bUseOpacityGradient = true;
    1316             :             }
    1317             :             else
    1318           0 :                 pDrawOpacityElement->addAttribute("draw:end", "100%");
    1319           0 :             pDrawGradientElement->addAttribute("draw:border", "0%");
    1320           0 :             mGraphicsGradientStyles.push_back(pDrawGradientElement);
    1321           0 :             mGraphicsGradientStyles.push_back(new TagCloseElement("draw:gradient"));
    1322           0 :             if (bUseOpacityGradient)
    1323             :             {
    1324           0 :                 mGraphicsGradientStyles.push_back(pDrawOpacityElement);
    1325           0 :                 mGraphicsGradientStyles.push_back(new TagCloseElement("draw:opacity"));
    1326             :             }
    1327             :         }
    1328             : 
    1329           0 :         if(!bUseOpacityGradient)
    1330           0 :             delete pDrawOpacityElement;
    1331             :     }
    1332             : 
    1333           0 :     if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "bitmap" &&
    1334           0 :             mxStyle["draw:fill-image"] && mxStyle["libwpg:mime-type"])
    1335             :     {
    1336           0 :         TagOpenElement *pDrawBitmapElement = new TagOpenElement("draw:fill-image");
    1337           0 :         WPXString sValue;
    1338           0 :         sValue.sprintf("Bitmap_%i", miBitmapIndex++);
    1339           0 :         pDrawBitmapElement->addAttribute("draw:name", sValue);
    1340           0 :         mGraphicsBitmapStyles.push_back(pDrawBitmapElement);
    1341           0 :         mGraphicsBitmapStyles.push_back(new TagOpenElement("office:binary-data"));
    1342           0 :         mGraphicsBitmapStyles.push_back(new CharDataElement(mxStyle["draw:fill-image"]->getStr()));
    1343           0 :         mGraphicsBitmapStyles.push_back(new TagCloseElement("office:binary-data"));
    1344           0 :         mGraphicsBitmapStyles.push_back(new TagCloseElement("draw:fill-image"));
    1345             :     }
    1346             : 
    1347           0 :     TagOpenElement *pStyleStyleElement = new TagOpenElement("style:style");
    1348           0 :     WPXString sValue;
    1349           0 :     sValue.sprintf("gr%i",  miGraphicsStyleIndex);
    1350           0 :     pStyleStyleElement->addAttribute("style:name", sValue);
    1351           0 :     pStyleStyleElement->addAttribute("style:family", "graphic");
    1352           0 :     pStyleStyleElement->addAttribute("style:parent-style-name", "standard");
    1353           0 :     mGraphicsAutomaticStyles.push_back(pStyleStyleElement);
    1354             : 
    1355           0 :     TagOpenElement *pStyleGraphicsPropertiesElement = new TagOpenElement("style:graphic-properties");
    1356             : 
    1357           0 :     if (mxStyle["draw:color-mode"] && mxStyle["draw:color-mode"]->getStr().len() > 0)
    1358           0 :         pStyleGraphicsPropertiesElement->addAttribute("draw:color-mode", mxStyle["draw:color-mode"]->getStr());
    1359           0 :     if (mxStyle["draw:luminance"] && mxStyle["draw:luminance"]->getStr().len() > 0)
    1360           0 :         pStyleGraphicsPropertiesElement->addAttribute("draw:luminance", mxStyle["draw:luminance"]->getStr());
    1361           0 :     if (mxStyle["draw:contrast"] && mxStyle["draw:contrast"]->getStr().len() > 0)
    1362           0 :         pStyleGraphicsPropertiesElement->addAttribute("draw:contrast", mxStyle["draw:contrast"]->getStr());
    1363           0 :     if (mxStyle["draw:gamma"] && mxStyle["draw:gamma"]->getStr().len() > 0)
    1364           0 :         pStyleGraphicsPropertiesElement->addAttribute("draw:gamma", mxStyle["draw:gamma"]->getStr());
    1365           0 :     if (mxStyle["draw:red"] && mxStyle["draw:red"]->getStr().len() > 0)
    1366           0 :         pStyleGraphicsPropertiesElement->addAttribute("draw:red", mxStyle["draw:red"]->getStr());
    1367           0 :     if (mxStyle["draw:green"] && mxStyle["draw:green"]->getStr().len() > 0)
    1368           0 :         pStyleGraphicsPropertiesElement->addAttribute("draw:green", mxStyle["draw:green"]->getStr());
    1369           0 :     if (mxStyle["draw:blue"] && mxStyle["draw:blue"]->getStr().len() > 0)
    1370           0 :         pStyleGraphicsPropertiesElement->addAttribute("draw:blue", mxStyle["draw:blue"]->getStr());
    1371             : 
    1372           0 :     if (mxStyle["draw:stroke"] && mxStyle["draw:stroke"]->getStr() == "none")
    1373           0 :         pStyleGraphicsPropertiesElement->addAttribute("draw:stroke", "none");
    1374             :     else
    1375             :     {
    1376           0 :         if (mxStyle["svg:stroke-width"])
    1377           0 :             pStyleGraphicsPropertiesElement->addAttribute("svg:stroke-width", mxStyle["svg:stroke-width"]->getStr());
    1378             : 
    1379           0 :         if (mxStyle["svg:stroke-color"])
    1380           0 :             pStyleGraphicsPropertiesElement->addAttribute("svg:stroke-color", mxStyle["svg:stroke-color"]->getStr());
    1381             : 
    1382           0 :         if (mxStyle["svg:stroke-opacity"])
    1383           0 :             pStyleGraphicsPropertiesElement->addAttribute("svg:stroke-opacity", mxStyle["svg:stroke-opacity"]->getStr());
    1384             : 
    1385           0 :         if (mxStyle["svg:stroke-linejoin"])
    1386           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:stroke-linejoin", mxStyle["svg:stroke-linejoin"]->getStr());
    1387             : 
    1388           0 :         if (mxStyle["svg:stroke-linecap"])
    1389           0 :             pStyleGraphicsPropertiesElement->addAttribute("svg:stoke-linecap", mxStyle["svg:stroke-linecap"]->getStr());
    1390             : 
    1391           0 :         if (mxStyle["draw:stroke"] && mxStyle["draw:stroke"]->getStr() == "dash")
    1392             :         {
    1393           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:stroke", "dash");
    1394           0 :             sValue.sprintf("Dash_%i", miDashIndex-1);
    1395           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:stroke-dash", sValue);
    1396             :         }
    1397             :         else
    1398           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:stroke", "solid");
    1399             :     }
    1400             : 
    1401           0 :     if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "none")
    1402           0 :         pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "none");
    1403             :     else
    1404             :     {
    1405           0 :         if (mxStyle["draw:shadow"])
    1406           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:shadow", mxStyle["draw:shadow"]->getStr());
    1407             :         else
    1408           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:shadow", "hidden");
    1409           0 :         if (mxStyle["draw:shadow-offset-x"])
    1410           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:shadow-offset-x", mxStyle["draw:shadow-offset-x"]->getStr());
    1411           0 :         if (mxStyle["draw:shadow-offset-y"])
    1412           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:shadow-offset-y", mxStyle["draw:shadow-offset-y"]->getStr());
    1413           0 :         if (mxStyle["draw:shadow-color"])
    1414           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:shadow-color", mxStyle["draw:shadow-color"]->getStr());
    1415           0 :         if (mxStyle["draw:shadow-opacity"])
    1416           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:shadow-opacity", mxStyle["draw:shadow-opacity"]->getStr());
    1417           0 :         if (mxStyle["svg:fill-rule"])
    1418           0 :             pStyleGraphicsPropertiesElement->addAttribute("svg:fill-rule", mxStyle["svg:fill-rule"]->getStr());
    1419             :     }
    1420             : 
    1421           0 :     if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "solid")
    1422             :     {
    1423           0 :         pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "solid");
    1424           0 :         if (mxStyle["draw:fill-color"])
    1425           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:fill-color", mxStyle["draw:fill-color"]->getStr());
    1426           0 :         if (mxStyle["draw:opacity"])
    1427           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:opacity", mxStyle["draw:opacity"]->getStr());
    1428             :     }
    1429             : 
    1430           0 :     if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "gradient")
    1431             :     {
    1432           0 :         if (!mxGradient.count() || mxGradient.count() >= 2)
    1433             :         {
    1434           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "gradient");
    1435           0 :             sValue.sprintf("Gradient_%i", miGradientIndex-1);
    1436           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:fill-gradient-name", sValue);
    1437           0 :             if (bUseOpacityGradient)
    1438             :             {
    1439           0 :                 sValue.sprintf("Transparency_%i", miGradientIndex-1);
    1440           0 :                 pStyleGraphicsPropertiesElement->addAttribute("draw:opacity-name", sValue);
    1441             :             }
    1442             :         }
    1443             :         else
    1444             :         {
    1445           0 :             if (mxGradient[0]["svg:stop-color"])
    1446             :             {
    1447           0 :                 pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "solid");
    1448           0 :                 pStyleGraphicsPropertiesElement->addAttribute("draw:fill-color", mxGradient[0]["svg:stop-color"]->getStr());
    1449             :             }
    1450             :             else
    1451           0 :                 pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "solid");
    1452             :         }
    1453             :     }
    1454             : 
    1455           0 :     if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "bitmap")
    1456             :     {
    1457           0 :         if (mxStyle["draw:fill-image"] && mxStyle["libwpg:mime-type"])
    1458             :         {
    1459           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "bitmap");
    1460           0 :             sValue.sprintf("Bitmap_%i", miBitmapIndex-1);
    1461           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:fill-image-name", sValue);
    1462           0 :             if (mxStyle["svg:width"])
    1463           0 :                 pStyleGraphicsPropertiesElement->addAttribute("draw:fill-image-width", mxStyle["svg:width"]->getStr());
    1464           0 :             if (mxStyle["svg:height"])
    1465           0 :                 pStyleGraphicsPropertiesElement->addAttribute("draw:fill-image-height", mxStyle["svg:height"]->getStr());
    1466           0 :             if (mxStyle["style:repeat"])
    1467           0 :                 pStyleGraphicsPropertiesElement->addAttribute("style:repeat", mxStyle["style:repeat"]->getStr());
    1468           0 :             if (mxStyle["draw:fill-image-ref-point"])
    1469           0 :                 pStyleGraphicsPropertiesElement->addAttribute("draw:fill-image-ref-point", mxStyle["draw:fill-image-ref-point"]->getStr());
    1470           0 :             if (mxStyle["draw:fill-image-ref-point-x"])
    1471           0 :                 pStyleGraphicsPropertiesElement->addAttribute("draw:fill-image-ref-point-x", mxStyle["draw:fill-image-ref-point-x"]->getStr());
    1472           0 :             if (mxStyle["draw:fill-image-ref-point-y"])
    1473           0 :                 pStyleGraphicsPropertiesElement->addAttribute("draw:fill-image-ref-point-y", mxStyle["draw:fill-image-ref-point-y"]->getStr());
    1474             :         }
    1475             :         else
    1476           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "none");
    1477             :     }
    1478             : 
    1479             : 
    1480           0 :     if(mxStyle["draw:marker-start-path"])
    1481             :     {
    1482           0 :         sValue.sprintf("StartMarker_%i", miStartMarkerIndex++);
    1483           0 :         pStyleGraphicsPropertiesElement->addAttribute("draw:marker-start", sValue);
    1484           0 :         if (mxStyle["draw:marker-start-width"])
    1485           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:marker-start-width", mxStyle["draw:marker-start-width"]->getStr());
    1486             :         else
    1487           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:marker-start-width", "0.118in");
    1488             :     }
    1489           0 :     if (mxStyle["draw:marker-end-path"])
    1490             :     {
    1491           0 :         sValue.sprintf("EndMarker_%i", miEndMarkerIndex++);
    1492           0 :         pStyleGraphicsPropertiesElement->addAttribute("draw:marker-end", sValue);
    1493           0 :         if (mxStyle["draw:marker-end-width"])
    1494           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:marker-end-width", mxStyle["draw:marker-end-width"]->getStr());
    1495             :         else
    1496           0 :             pStyleGraphicsPropertiesElement->addAttribute("draw:marker-end-width", "0.118in");
    1497             :     }
    1498           0 :     if (mxStyle["style:mirror"])
    1499           0 :         pStyleGraphicsPropertiesElement->addAttribute("style:mirror", mxStyle["style:mirror"]->getStr());
    1500             : 
    1501           0 :     mGraphicsAutomaticStyles.push_back(pStyleGraphicsPropertiesElement);
    1502           0 :     mGraphicsAutomaticStyles.push_back(new TagCloseElement("style:graphic-properties"));
    1503             : 
    1504           0 :     mGraphicsAutomaticStyles.push_back(new TagCloseElement("style:style"));
    1505           0 :     miGraphicsStyleIndex++;
    1506           0 : }
    1507             : 
    1508           0 : void OdgGenerator::startEmbeddedGraphics(const WPXPropertyList &)
    1509             : {
    1510           0 : }
    1511             : 
    1512           0 : void OdgGenerator::endEmbeddedGraphics()
    1513             : {
    1514           0 : }
    1515             : 
    1516           0 : void OdgGenerator::startTextObject(const WPXPropertyList &propList, const WPXPropertyListVector &)
    1517             : {
    1518           0 :     TagOpenElement *pDrawFrameOpenElement = new TagOpenElement("draw:frame");
    1519           0 :     TagOpenElement *pStyleStyleOpenElement = new TagOpenElement("style:style");
    1520             : 
    1521           0 :     WPXString sValue;
    1522           0 :     sValue.sprintf("gr%i",  mpImpl->miGraphicsStyleIndex++);
    1523           0 :     pStyleStyleOpenElement->addAttribute("style:name", sValue);
    1524           0 :     pStyleStyleOpenElement->addAttribute("style:family", "graphic");
    1525           0 :     pStyleStyleOpenElement->addAttribute("style:parent-style-name", "standard");
    1526           0 :     mpImpl->mGraphicsAutomaticStyles.push_back(pStyleStyleOpenElement);
    1527             : 
    1528           0 :     pDrawFrameOpenElement->addAttribute("draw:style-name", sValue);
    1529           0 :     pDrawFrameOpenElement->addAttribute("draw:layer", "layout");
    1530             : 
    1531           0 :     TagOpenElement *pStyleGraphicPropertiesOpenElement = new TagOpenElement("style:graphic-properties");
    1532           0 :     pStyleGraphicPropertiesOpenElement->addAttribute("draw:stroke", "none");
    1533           0 :     pStyleGraphicPropertiesOpenElement->addAttribute("svg:stroke-color", "#000000");
    1534           0 :     pStyleGraphicPropertiesOpenElement->addAttribute("draw:fill", "none");
    1535           0 :     pStyleGraphicPropertiesOpenElement->addAttribute("draw:fill-color", "#ffffff");
    1536             : 
    1537           0 :     double x = 0.0;
    1538           0 :     double y = 0.0;
    1539           0 :     double height = 0.0;
    1540           0 :     double width = 0.0;
    1541           0 :     if (propList["svg:x"])
    1542           0 :         x = propList["svg:x"]->getDouble();
    1543           0 :     if (propList["svg:y"])
    1544           0 :         y = propList["svg:y"]->getDouble();
    1545           0 :     if (propList["svg:width"])
    1546           0 :         width = propList["svg:width"]->getDouble();
    1547           0 :     if (propList["svg:height"])
    1548           0 :         height = propList["svg:height"]->getDouble();
    1549             : 
    1550           0 :     double angle(propList["libwpg:rotate"] ? - M_PI * propList["libwpg:rotate"]->getDouble() / 180.0 : 0.0);
    1551           0 :     if (angle != 0.0)
    1552             :     {
    1553           0 :         double deltax((width*cos(angle)+height*sin(angle)-width)/2.0);
    1554           0 :         double deltay((-width*sin(angle)+height*cos(angle)-height)/2.0);
    1555           0 :         x -= deltax;
    1556           0 :         y -= deltay;
    1557             :     }
    1558             : 
    1559           0 :     if (!propList["svg:width"] && !propList["svg:height"])
    1560             :     {
    1561           0 :         if (!propList["fo:min-width"])
    1562             :         {
    1563           0 :             pDrawFrameOpenElement->addAttribute("fo:min-width", "1in");
    1564           0 :             pStyleGraphicPropertiesOpenElement->addAttribute("fo:min-width", "1in");
    1565             :         }
    1566           0 :         pDrawFrameOpenElement->addAttribute("svg:width", "10in");
    1567             :     }
    1568             :     else
    1569             :     {
    1570           0 :         if(propList["svg:width"])
    1571           0 :             pDrawFrameOpenElement->addAttribute("svg:width", propList["svg:width"]->getStr());
    1572           0 :         if(propList["svg:height"])
    1573           0 :             pDrawFrameOpenElement->addAttribute("svg:height", propList["svg:height"]->getStr());
    1574             :     }
    1575           0 :     if (propList["fo:min-width"])
    1576             :     {
    1577           0 :         pDrawFrameOpenElement->addAttribute("fo:min-width", propList["fo:min-width"]->getStr());
    1578           0 :         pStyleGraphicPropertiesOpenElement->addAttribute("fo:min-width", propList["fo:min-width"]->getStr());
    1579             :     }
    1580           0 :     if (propList["fo:min-height"])
    1581             :     {
    1582           0 :         pDrawFrameOpenElement->addAttribute("fo:min-height", propList["fo:min-height"]->getStr());
    1583           0 :         pStyleGraphicPropertiesOpenElement->addAttribute("fo:min-height", propList["fo:min-height"]->getStr());
    1584             :     }
    1585           0 :     if (propList["fo:max-width"])
    1586             :     {
    1587           0 :         pDrawFrameOpenElement->addAttribute("fo:max-width", propList["fo:max-height"]->getStr());
    1588           0 :         pStyleGraphicPropertiesOpenElement->addAttribute("fo:max-width", propList["fo:max-width"]->getStr());
    1589             :     }
    1590           0 :     if (propList["fo:max-height"])
    1591             :     {
    1592           0 :         pDrawFrameOpenElement->addAttribute("fo:max-height", propList["fo:max-height"]->getStr());
    1593           0 :         pStyleGraphicPropertiesOpenElement->addAttribute("fo:max-height", propList["fo:max-height"]->getStr());
    1594             :     }
    1595           0 :     if (propList["fo:padding-top"])
    1596             :     {
    1597           0 :         pDrawFrameOpenElement->addAttribute("fo:padding-top", propList["fo:padding-top"]->getStr());
    1598           0 :         pStyleGraphicPropertiesOpenElement->addAttribute("fo:padding-top", propList["fo:padding-top"]->getStr());
    1599             :     }
    1600           0 :     if (propList["fo:padding-bottom"])
    1601             :     {
    1602           0 :         pDrawFrameOpenElement->addAttribute("fo:padding-bottom", propList["fo:padding-bottom"]->getStr());
    1603           0 :         pStyleGraphicPropertiesOpenElement->addAttribute("fo:padding-bottom", propList["fo:padding-bottom"]->getStr());
    1604             :     }
    1605           0 :     if (propList["fo:padding-left"])
    1606             :     {
    1607           0 :         pDrawFrameOpenElement->addAttribute("fo:padding-left", propList["fo:padding-left"]->getStr());
    1608           0 :         pStyleGraphicPropertiesOpenElement->addAttribute("fo:padding-left", propList["fo:padding-left"]->getStr());
    1609             :     }
    1610           0 :     if (propList["fo:padding-right"])
    1611             :     {
    1612           0 :         pDrawFrameOpenElement->addAttribute("fo:padding-right", propList["fo:padding-right"]->getStr());
    1613           0 :         pStyleGraphicPropertiesOpenElement->addAttribute("fo:padding-right", propList["fo:padding-right"]->getStr());
    1614             :     }
    1615           0 :     if (propList["draw:textarea-vertical-align"])
    1616             :     {
    1617           0 :         pDrawFrameOpenElement->addAttribute("draw:textarea-vertical-align", propList["draw:textarea-vertical-align"]->getStr());
    1618           0 :         pStyleGraphicPropertiesOpenElement->addAttribute("draw:textarea-vertical-align", propList["draw:textarea-vertical-align"]->getStr());
    1619             :     }
    1620           0 :     if (propList["draw:fill"])
    1621             :     {
    1622           0 :         pDrawFrameOpenElement->addAttribute("draw:fill", propList["draw:fill"]->getStr());
    1623           0 :         pStyleGraphicPropertiesOpenElement->addAttribute("draw:fill", propList["draw:fill"]->getStr());
    1624             :     }
    1625           0 :     if (propList["draw:fill-color"])
    1626             :     {
    1627           0 :         pDrawFrameOpenElement->addAttribute("draw:fill-color", propList["draw:fill-color"]->getStr());
    1628           0 :         pStyleGraphicPropertiesOpenElement->addAttribute("draw:fill-color", propList["draw:fill-color"]->getStr());
    1629             :     }
    1630           0 :     if (propList["draw:opacity"])
    1631             :     {
    1632           0 :         pDrawFrameOpenElement->addAttribute("draw:opacity", propList["draw:opacity"]->getStr());
    1633           0 :         pStyleGraphicPropertiesOpenElement->addAttribute("draw:opacity", propList["draw:opacity"]->getStr());
    1634             :     }
    1635             : 
    1636           0 :     WPXProperty *svg_x = WPXPropertyFactory::newInchProp(x);
    1637           0 :     WPXProperty *svg_y = WPXPropertyFactory::newInchProp(y);
    1638           0 :     if (angle != 0.0)
    1639             :     {
    1640           0 :         WPXProperty *libwpg_rotate = WPXPropertyFactory::newDoubleProp(angle);
    1641             :         sValue.sprintf("rotate (%s) translate(%s, %s)",
    1642           0 :                        libwpg_rotate->getStr().cstr(),
    1643           0 :                        svg_x->getStr().cstr(),
    1644           0 :                        svg_y->getStr().cstr());
    1645           0 :         delete libwpg_rotate;
    1646           0 :         pDrawFrameOpenElement->addAttribute("draw:transform", sValue);
    1647             :     }
    1648             :     else
    1649             :     {
    1650           0 :         if (propList["svg:x"])
    1651           0 :             pDrawFrameOpenElement->addAttribute("svg:x", svg_x->getStr());
    1652           0 :         if (propList["svg:y"])
    1653           0 :             pDrawFrameOpenElement->addAttribute("svg:y", svg_y->getStr());
    1654             :     }
    1655           0 :     delete svg_x;
    1656           0 :     delete svg_y;
    1657           0 :     mpImpl->mBodyElements.push_back(pDrawFrameOpenElement);
    1658           0 :     mpImpl->mBodyElements.push_back(new TagOpenElement("draw:text-box"));
    1659           0 :     mpImpl->mGraphicsAutomaticStyles.push_back(pStyleGraphicPropertiesOpenElement);
    1660           0 :     mpImpl->mGraphicsAutomaticStyles.push_back(new TagCloseElement("style:graphic-properties"));
    1661           0 :     mpImpl->mGraphicsAutomaticStyles.push_back(new TagCloseElement("style:style"));
    1662           0 :     mpImpl->mbIsTextBox = true;
    1663           0 : }
    1664             : 
    1665           0 : void OdgGenerator::endTextObject()
    1666             : {
    1667           0 :     if (mpImpl->mbIsTextBox)
    1668             :     {
    1669           0 :         mpImpl->mBodyElements.push_back(new TagCloseElement("draw:text-box"));
    1670           0 :         mpImpl->mBodyElements.push_back(new TagCloseElement("draw:frame"));
    1671           0 :         mpImpl->mbIsTextBox = false;
    1672             :     }
    1673           0 : }
    1674             : 
    1675           0 : void OdgGenerator::startTextLine(const WPXPropertyList &propList)
    1676             : {
    1677           0 :     WPXPropertyList finalPropList(propList);
    1678           0 :     finalPropList.insert("style:parent-style-name", "Standard");
    1679           0 :     WPXString paragName = mpImpl->mParagraphManager.findOrAdd(finalPropList, WPXPropertyListVector());
    1680             : 
    1681             : 
    1682             :     // create a document element corresponding to the paragraph, and append it to our list of document elements
    1683           0 :     TagOpenElement *pParagraphOpenElement = new TagOpenElement("text:p");
    1684           0 :     pParagraphOpenElement->addAttribute("text:style-name", paragName);
    1685           0 :     mpImpl->mBodyElements.push_back(pParagraphOpenElement);
    1686           0 : }
    1687             : 
    1688           0 : void OdgGenerator::endTextLine()
    1689             : {
    1690           0 :     mpImpl->mBodyElements.push_back(new TagCloseElement("text:p"));
    1691           0 : }
    1692             : 
    1693           0 : void OdgGenerator::startTextSpan(const WPXPropertyList &propList)
    1694             : {
    1695           0 :     if (propList["style:font-name"])
    1696           0 :         mpImpl->mFontManager.findOrAdd(propList["style:font-name"]->getStr().cstr());
    1697             : 
    1698           0 :     WPXString sName = mpImpl->mSpanManager.findOrAdd(propList);
    1699             : 
    1700           0 :     TagOpenElement *pSpanOpenElement = new TagOpenElement("text:span");
    1701           0 :     pSpanOpenElement->addAttribute("text:style-name", sName.cstr());
    1702           0 :     mpImpl->mBodyElements.push_back(pSpanOpenElement);
    1703           0 : }
    1704             : 
    1705           0 : void OdgGenerator::endTextSpan()
    1706             : {
    1707           0 :     mpImpl->mBodyElements.push_back(new TagCloseElement("text:span"));
    1708           0 : }
    1709             : 
    1710           0 : void OdgGenerator::insertText(const WPXString &text)
    1711             : {
    1712           0 :     WPXString out;
    1713           0 :     WPXString::Iter i(text);
    1714           0 :     for (i.rewind(); i.next();)
    1715             :     {
    1716           0 :         if ((*i()) == '\n' || (*i()) == '\t')
    1717             :         {
    1718           0 :             if (out.len() != 0)
    1719             :             {
    1720           0 :                 DocumentElement *pText = new TextElement(out);
    1721           0 :                 mpImpl->mBodyElements.push_back(pText);
    1722           0 :                 out.clear();
    1723             :             }
    1724           0 :             if ((*i()) == '\n')
    1725             :             {
    1726           0 :                 mpImpl->mBodyElements.push_back(new TagOpenElement("text:line-break"));
    1727           0 :                 mpImpl->mBodyElements.push_back(new TagCloseElement("text:line-break"));
    1728             :             }
    1729           0 :             else if ((*i()) == '\t')
    1730             :             {
    1731           0 :                 mpImpl->mBodyElements.push_back(new TagOpenElement("text:tab"));
    1732           0 :                 mpImpl->mBodyElements.push_back(new TagCloseElement("text:tab"));
    1733             :             }
    1734             :         }
    1735             :         else
    1736             :         {
    1737           0 :             out.append(i());
    1738             :         }
    1739             :     }
    1740           0 :     if (out.len() != 0)
    1741             :     {
    1742           0 :         DocumentElement *pText = new TextElement(out);
    1743           0 :         mpImpl->mBodyElements.push_back(pText);
    1744           0 :     }
    1745           0 : }
    1746             : 
    1747             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10