Date: prev next · Thread: first prev next last
2012 Archives by date, by thread · List index


Hello, good people,

This attached patch is uploading a new libcdr that fixes several
position problems as those reported once in one article of heise.de. It
is also fixing some problems we had with filling of shapes where things
that were not supposed to be filled were filled. It also fixes a bug on
windows where we were truncating the values when reading a palette of
indexed bitmap.

For careful reviever, I attach a diff of the relevant parts between
0.0.8 and 0.0.9. This release also adds Visual Studio 2008 and 2010
project files, but they are not relevant for 3-6 branch since the libcdr
is built there only using the makefile.mk contained in the tarball.

It is not a cherry-pick from master. The module is gbuildified in master
and the patch will have nothing in common with this one.

Thanks for a courageous person who will review this

Cheers

Fridrich
From 324f7e4c196269ad1fa4ee6d13d829302255c9bd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fridrich=20=C5=A0trba?= <fridrich.strba@bluewin.ch>
Date: Fri, 5 Oct 2012 15:41:15 +0200
Subject: [PATCH] New release libcdr 0.0.9, fixes fdo#55522 and partly
 fdo#54785

Change-Id: I85516bcb97cc066fb25bb74ef253ff6ae6942d10
---
 libcdr/README                 |    2 +-
 libcdr/libcdr-0.0.8-msc.patch |   10 ----------
 libcdr/makefile.mk            |    6 ++----
 ooo.lst.in                    |    2 +-
 4 files changed, 4 insertions(+), 16 deletions(-)
 delete mode 100644 libcdr/libcdr-0.0.8-msc.patch

diff --git a/libcdr/README b/libcdr/README
index d3ba94d..9aa5ada 100644
--- a/libcdr/README
+++ b/libcdr/README
@@ -1,3 +1,3 @@
 Library parsing the Corel cdr documents.
 
-I couldn't find an upstream for this library - although I did only try a primitive Google search.
+http://wiki.freedesktop.org/wiki/Software/libcdr
diff --git a/libcdr/libcdr-0.0.8-msc.patch b/libcdr/libcdr-0.0.8-msc.patch
deleted file mode 100644
index 6a44e7d..0000000
--- a/libcdr/libcdr-0.0.8-msc.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- misc/libcdr-0.0.8/src/lib/libcdr_utils.h   2012-06-06 13:42:03.000000000 +0200
-+++ misc/build/libcdr-0.0.8/src/lib/libcdr_utils.h     2012-06-11 15:09:43.305289500 +0200
-@@ -50,6 +50,7 @@
- typedef unsigned char uint8_t;
- typedef unsigned short uint16_t;
- typedef unsigned uint32_t;
-+typedef short int16_t;
- typedef int int32_t;
- typedef unsigned __int64 uint64_t;
- 
diff --git a/libcdr/makefile.mk b/libcdr/makefile.mk
index 771ac46..0a8df79 100755
--- a/libcdr/makefile.mk
+++ b/libcdr/makefile.mk
@@ -59,10 +59,8 @@ INCPRE+=$(LCMS2_CFLAGS)
 INCPRE+=$(SOLARVER)$/$(INPATH)$/inc$/lcms2
 .ENDIF
 
-TARFILE_NAME=libcdr-0.0.8
-TARFILE_MD5=ce5a1def34578b75959ac31210f031f6
-
-PATCH_FILES = libcdr-0.0.8-msc.patch
+TARFILE_NAME=libcdr-0.0.9
+TARFILE_MD5=3c0037fb07dea2f0bbae8386fa7c6a9a
 
 BUILD_ACTION=dmake $(MFLAGS) $(CALLMACROS)
 BUILD_DIR=src$/lib
diff --git a/ooo.lst.in b/ooo.lst.in
index f4d8db9..02d14b0 100644
--- a/ooo.lst.in
+++ b/ooo.lst.in
@@ -90,7 +90,7 @@ f02578f5218f217a9f20e9c30e119c6a-boost_1_44_0.tar.bz2
 94e7f271e38c976462558b4278590178-libvisio-0.0.19.tar.bz2
 e7a384790b13c29113e22e596ade9687-LinLibertineG-20120116.zip
 0d2dcdfbf28d6208751b33057f5361f0-libcmis-0.2.3.tar.gz
-ce5a1def34578b75959ac31210f031f6-libcdr-0.0.8.tar.bz2
+3c0037fb07dea2f0bbae8386fa7c6a9a-libcdr-0.0.9.tar.bz2
 327348d67c979c88c2dec59a23a17d85-lcms2-2.3.tar.gz
 @GOOGLE_DOCS_EXTENSION_PACK@
 @FREETYPE_TARBALL@
-- 
1.7.10.4

--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@ AC_PREREQ([2.65])
 # ====================
 m4_define([libcdr_version_major],[0])
 m4_define([libcdr_version_minor],[0])
-m4_define([libcdr_version_micro],[8])
+m4_define([libcdr_version_micro],[9])
 m4_define([libcdr_version],[libcdr_version_major.libcdr_version_minor.libcdr_version_micro])
 
 # =============
@@ -23,6 +23,7 @@ AC_LANG([C++])
 # ===========================
 # Find required base packages
 # ===========================
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
 AC_PROG_CC
 AC_PROG_CPP
 AC_PROG_CXX
@@ -162,6 +163,8 @@ AC_ARG_ENABLE([debug],
 )
 AS_IF([test "x$enable_debug" = "xyes"], [
        DEBUG_CXXFLAGS="-DDEBUG -g"
+       CXXFLAGS="$CXXFLAGS -O0"
+       CFLAGS="$CFLAGS -O0"
 ], [
        DEBUG_CXXFLAGS="-DNDEBUG"
 ])
diff --git a/src/lib/CDRCollector.h b/src/lib/CDRCollector.h
index dd748aa..a4b2e90 100644
--- a/src/lib/CDRCollector.h
+++ b/src/lib/CDRCollector.h
@@ -98,7 +98,7 @@ public:
   virtual void collectArcTo(double rx, double ry, bool largeArc, bool sweep, double x, double y) = 
0;
   virtual void collectClosePath() = 0;
   virtual void collectLevel(unsigned level) = 0;
-  virtual void collectTransform(double v0, double v1, double x, double v3, double v4, double y, 
bool considerGroupTransform) = 0;
+  virtual void collectTransform(const CDRTransforms &transforms, bool considerGroupTransform) = 0;
   virtual void collectFildId(unsigned id) = 0;
   virtual void collectOutlId(unsigned id) = 0;
   virtual void collectFild(unsigned id, unsigned short fillType, const CDRColor &color1, const 
CDRColor &color2, const CDRGradient &gradient, const CDRImageFill &imageFill) = 0;
@@ -114,7 +114,7 @@ public:
   virtual void collectBmp(unsigned imageId, const std::vector<unsigned char> &bitmap) = 0;
   virtual void collectBmpf(unsigned patternId, unsigned width, unsigned height, const 
std::vector<unsigned char> &pattern) = 0;
   virtual void collectPpdt(const std::vector<std::pair<double, double> > &points, const 
std::vector<unsigned> &knotVector) = 0;
-  virtual void collectFillTransform(double v0, double v1, double x, double v3, double v4, double 
y) = 0;
+  virtual void collectFillTransform(const CDRTransforms &fillTrafos) = 0;
   virtual void collectFillOpacity(double opacity) = 0;
   virtual void collectPolygon() = 0;
   virtual void collectSpline() = 0;
diff --git a/src/lib/CDRContentCollector.cpp b/src/lib/CDRContentCollector.cpp
index 2a0ecfa..d40027f 100644
--- a/src/lib/CDRContentCollector.cpp
+++ b/src/lib/CDRContentCollector.cpp
@@ -53,7 +53,7 @@ libcdr::CDRContentCollector::CDRContentCollector(libcdr::CDRParserState &ps, lib
   m_page(ps.m_pages[0]), m_pageIndex(0), m_currentFildId(0.0), m_currentOutlId(0), m_spnd(0),
   m_currentObjectLevel(0), m_currentGroupLevel(0), m_currentVectLevel(0), m_currentPageLevel(0),
   m_currentImage(), m_currentText(), m_currentTextOffsetX(0.0), m_currentTextOffsetY(0.0),
-  m_currentBBox(), m_currentPath(), m_currentTransform(), m_fillTransform(),
+  m_currentBBox(), m_currentPath(), m_currentTransforms(), m_fillTransforms(),
   m_polygon(0), m_isInPolygon(false), m_isInSpline(false), m_outputElements(0),
   m_contentOutputElements(), m_fillOutputElements(),
   m_groupLevels(), m_groupTransforms(), m_splineData(), m_fillOpacity(1.0), m_ps(ps)
@@ -124,7 +124,7 @@ void libcdr::CDRContentCollector::collectGroup(unsigned level)
   outputElement.addEndGroup();
   m_outputElements->push(outputElement);
   m_groupLevels.push(level);
-  m_groupTransforms.push(CDRTransform());
+  m_groupTransforms.push(CDRTransforms());
 }
 
 void libcdr::CDRContentCollector::collectVect(unsigned level)
@@ -209,6 +209,7 @@ void libcdr::CDRContentCollector::_flushCurrentPath()
     m_splineData.clear();
     m_isInSpline = false;
     bool firstPoint = true;
+    bool wasMove = false;
     double initialX = 0.0;
     double initialY = 0.0;
     double previousX = 0.0;
@@ -220,20 +221,25 @@ void libcdr::CDRContentCollector::_flushCurrentPath()
     _fillProperties(style, gradient);
     _lineProperties(style);
     outputElement.addStyle(style, gradient);
-    m_currentPath.transform(m_currentTransform);
+    m_currentPath.transform(m_currentTransforms);
     if (!m_groupTransforms.empty())
       m_currentPath.transform(m_groupTransforms.top());
     CDRTransform tmpTrafo(1.0, 0.0, -m_page.offsetX, 0.0, 1.0, -m_page.offsetY);
     m_currentPath.transform(tmpTrafo);
     tmpTrafo = CDRTransform(1.0, 0.0, 0.0, 0.0, -1.0, m_page.height);
     m_currentPath.transform(tmpTrafo);
-    WPXPropertyListVector tmpPath;
-    m_currentPath.writeOut(tmpPath);
+
+    std::vector<WPXPropertyList> tmpPath;
+
     WPXPropertyListVector path;
-    WPXPropertyListVector::Iter i(tmpPath);
-    bool ignoreM = false;
+    m_currentPath.writeOut(path);
+
+    bool isPathClosed = m_currentPath.isClosed();
+
+    WPXPropertyListVector::Iter i(path);
     for (i.rewind(); i.next();)
     {
+      bool ignoreM = false;
       if (!i()["libwpg:path-action"])
         continue;
       if (i()["svg:x"] && i()["svg:y"])
@@ -245,58 +251,95 @@ void libcdr::CDRContentCollector::_flushCurrentPath()
           initialX = x;
           initialY = y;
           firstPoint = false;
+          wasMove = true;
         }
         else if (i()["libwpg:path-action"]->getStr() == "M")
         {
+          // This is needed for a good generation of path from polygon
           if (CDR_ALMOST_ZERO(previousX - x) && CDR_ALMOST_ZERO(previousY - y))
             ignoreM = true;
           else
           {
-            if ((CDR_ALMOST_ZERO(initialX - previousX) && CDR_ALMOST_ZERO(initialY - previousY)) 
|| (style["draw:fill"] && style["draw:fill"]->getStr() != "none"))
+            if (!tmpPath.empty())
             {
-              WPXPropertyList node;
-              node.insert("libwpg:path-action", "Z");
-              path.append(node);
+              if (!wasMove)
+              {
+                if ((CDR_ALMOST_ZERO(initialX - previousX) && CDR_ALMOST_ZERO(initialY - 
previousY)) || isPathClosed)
+                {
+                  WPXPropertyList node;
+                  node.insert("libwpg:path-action", "Z");
+                  tmpPath.push_back(node);
+                }
+              }
+              else
+              {
+                tmpPath.pop_back();
+              }
             }
+          }
+
+          if (!ignoreM)
+          {
             initialX = x;
             initialY = y;
+            wasMove = true;
           }
+
+        }
+        else
+          wasMove = false;
+
+        if (!ignoreM)
+        {
+          tmpPath.push_back(i());
+          previousX = x;
+          previousY = y;
         }
+
       }
-      previousX = x;
-      previousY = y;
-      if (!ignoreM)
-        path.append(i());
-      ignoreM = false;
     }
-    if ((CDR_ALMOST_ZERO(initialX - previousX) && CDR_ALMOST_ZERO(initialY - previousY)) || 
(style["draw:fill"] && style["draw:fill"]->getStr() != "none"))
+    if (!tmpPath.empty())
     {
-      WPXPropertyList node;
-      node.insert("libwpg:path-action", "Z");
-      path.append(node);
+      if (!wasMove)
+      {
+        if ((CDR_ALMOST_ZERO(initialX - previousX) && CDR_ALMOST_ZERO(initialY - previousY)) || 
isPathClosed)
+        {
+          WPXPropertyList closedPath;
+          closedPath.insert("libwpg:path-action", "Z");
+          tmpPath.push_back(closedPath);
+        }
+      }
+      else
+        tmpPath.pop_back();
     }
+    if (!tmpPath.empty())
+    {
+      WPXPropertyListVector outputPath;
+      for (std::vector<WPXPropertyList>::const_iterator iter = tmpPath.begin(); iter != 
tmpPath.end(); ++iter)
+        outputPath.append(*iter);
+
+      outputElement.addPath(outputPath);
 
-    outputElement.addPath(path);
+    }
     m_currentPath.clear();
   }
+
   if (m_currentImage.getImage().size())
   {
     double cx = m_currentImage.getMiddleX();
     double cy = m_currentImage.getMiddleY();
-    m_currentTransform.applyToPoint(cx, cy);
+    m_currentTransforms.applyToPoint(cx, cy);
     if (!m_groupTransforms.empty())
       m_groupTransforms.top().applyToPoint(cx, cy);
     CDRTransform tmpTrafo(1.0, 0.0, -m_page.offsetX, 0.0, 1.0, -m_page.offsetY);
     tmpTrafo.applyToPoint(cx, cy);
     tmpTrafo = CDRTransform(1.0, 0.0, 0.0, 0.0, -1.0, m_page.height);
     tmpTrafo.applyToPoint(cx, cy);
-    double scaleX = (m_currentTransform.m_v0 < 0.0 ? -1.0 : 1.0)*sqrt(m_currentTransform.m_v0 * 
m_currentTransform.m_v0 + m_currentTransform.m_v1 * m_currentTransform.m_v1);
-    double scaleY = (m_currentTransform.m_v3 < 0.0 ? -1.0 : 1.0)*sqrt(m_currentTransform.m_v3 * 
m_currentTransform.m_v3 + m_currentTransform.m_v4 * m_currentTransform.m_v4);
-    bool flipX(scaleX < 0);
-    bool flipY(scaleY < 0);
-    double width = fabs(scaleX)*m_currentImage.getWidth();
-    double height = fabs(scaleY)*m_currentImage.getHeight();
-    double rotate = -atan2(m_currentTransform.m_v3, m_currentTransform.m_v4);
+    bool flipX(m_currentTransforms.getFlipX());
+    bool flipY(m_currentTransforms.getFlipY());
+    double width = m_currentTransforms.getScaleX() * m_currentImage.getWidth();
+    double height = m_currentTransforms.getScaleY() * m_currentImage.getHeight();
+    double rotate = m_currentTransforms.getRotation();
 
     WPXPropertyList propList;
 
@@ -332,7 +375,7 @@ void libcdr::CDRContentCollector::_flushCurrentPath()
   {
     double currentTextOffsetX = 0.0;
     double currentTextOffsetY = 0.0;
-    m_currentTransform.applyToPoint(currentTextOffsetX, currentTextOffsetY);
+    m_currentTransforms.applyToPoint(currentTextOffsetX, currentTextOffsetY);
     if (!m_groupTransforms.empty())
       m_groupTransforms.top().applyToPoint(currentTextOffsetX, currentTextOffsetY);
     WPXPropertyList textFrameProps;
@@ -370,23 +413,23 @@ void libcdr::CDRContentCollector::_flushCurrentPath()
   m_currentImage = libcdr::CDRImage();
   if (!outputElement.empty())
     m_outputElements->push(outputElement);
-  m_currentTransform = libcdr::CDRTransform();
-  m_fillTransform = libcdr::CDRTransform();
+  m_currentTransforms.clear();
+  m_fillTransforms = libcdr::CDRTransforms();
   m_fillOpacity = 1.0;
   m_currentText = CDRText();
 }
 
-void libcdr::CDRContentCollector::collectTransform(double v0, double v1, double x0, double v3, 
double v4, double y0, bool considerGroupTransform)
+void libcdr::CDRContentCollector::collectTransform(const CDRTransforms &transforms, bool 
considerGroupTransform)
 {
   if (m_currentObjectLevel)
-    m_currentTransform = libcdr::CDRTransform(v0, v1, x0, v3, v4, y0);
+    m_currentTransforms = transforms;
   else if (!m_groupLevels.empty() && considerGroupTransform)
-    m_groupTransforms.top() = CDRTransform(v0, v1, x0, v3, v4, y0);
+    m_groupTransforms.top() = transforms;
 }
 
-void libcdr::CDRContentCollector::collectFillTransform(double v0, double v1, double x0, double v3, 
double v4, double y0)
+void libcdr::CDRContentCollector::collectFillTransform(const CDRTransforms &fillTrafos)
 {
-  m_fillTransform = libcdr::CDRTransform(v0, v1, x0, v3, v4, y0);
+  m_fillTransforms = fillTrafos;
 }
 
 void libcdr::CDRContentCollector::collectLevel(unsigned level)
@@ -637,8 +680,8 @@ void libcdr::CDRContentCollector::_fillProperties(WPXPropertyList &propList, WPX
             double scaleY = 1.0;
             if (iter->second.imageFill.flags & 0x04) // scale fill with image
             {
-              scaleX = sqrt(m_currentTransform.m_v0 * m_currentTransform.m_v0 + 
m_currentTransform.m_v1 * m_currentTransform.m_v1);
-              scaleY = sqrt(m_currentTransform.m_v3 * m_currentTransform.m_v3 + 
m_currentTransform.m_v4 * m_currentTransform.m_v4);
+              scaleX = m_currentTransforms.getScaleX();
+              scaleY = m_currentTransforms.getScaleY();
             }
             propList.insert("svg:width", iter->second.imageFill.width * scaleX);
             propList.insert("svg:height", iter->second.imageFill.height * scaleY);
@@ -648,23 +691,23 @@ void libcdr::CDRContentCollector::_fillProperties(WPXPropertyList &propList, 
WPX
           {
             if (iter->second.imageFill.xOffset != 0.0 && iter->second.imageFill.xOffset != 1.0)
               propList.insert("draw:fill-image-ref-point-x", iter->second.imageFill.xOffset, 
WPX_PERCENT);
-            if (iter->second.imageFill.yOffset != 0.0 && iter->second.imageFill.yOffset != 0.0)
+            if (iter->second.imageFill.yOffset != 0.0 && iter->second.imageFill.yOffset != 1.0)
               propList.insert("draw:fill-image-ref-point-y", iter->second.imageFill.yOffset, 
WPX_PERCENT);
           }
           else
           {
-            if (m_fillTransform.m_x0 != 0.0)
+            if (m_fillTransforms.getTranslateX() != 0.0)
             {
-              double xOffset = m_fillTransform.m_x0 / iter->second.imageFill.width;
+              double xOffset = m_fillTransforms.getTranslateX() / iter->second.imageFill.width;
               while (xOffset < 0.0)
                 xOffset += 1.0;
               while (xOffset > 1.0)
                 xOffset -= 1.0;
               propList.insert("draw:fill-image-ref-point-x", xOffset, WPX_PERCENT);
             }
-            if (m_fillTransform.m_y0 != 0.0)
+            if (m_fillTransforms.getTranslateY() != 0.0)
             {
-              double yOffset = m_fillTransform.m_y0 / iter->second.imageFill.width;
+              double yOffset = m_fillTransforms.getTranslateY() / iter->second.imageFill.width;
               while (yOffset < 0.0)
                 yOffset += 1.0;
               while (yOffset > 1.0)
@@ -703,8 +746,8 @@ void libcdr::CDRContentCollector::_fillProperties(WPXPropertyList &propList, WPX
             double scaleY = 1.0;
             if (iter->second.imageFill.flags & 0x04) // scale fill with image
             {
-              scaleX = sqrt(m_currentTransform.m_v0 * m_currentTransform.m_v0 + 
m_currentTransform.m_v1 * m_currentTransform.m_v1);
-              scaleY = sqrt(m_currentTransform.m_v3 * m_currentTransform.m_v3 + 
m_currentTransform.m_v4 * m_currentTransform.m_v4);
+              scaleX = m_currentTransforms.getScaleX();
+              scaleY = m_currentTransforms.getScaleY();
             }
             propList.insert("svg:width", iter->second.imageFill.width * scaleX);
             propList.insert("svg:height", iter->second.imageFill.height * scaleY);
@@ -714,23 +757,23 @@ void libcdr::CDRContentCollector::_fillProperties(WPXPropertyList &propList, 
WPX
           {
             if (iter->second.imageFill.xOffset != 0.0 && iter->second.imageFill.xOffset != 1.0)
               propList.insert("draw:fill-image-ref-point-x", iter->second.imageFill.xOffset, 
WPX_PERCENT);
-            if (iter->second.imageFill.yOffset != 0.0 && iter->second.imageFill.yOffset != 0.0)
+            if (iter->second.imageFill.yOffset != 0.0 && iter->second.imageFill.yOffset != 1.0)
               propList.insert("draw:fill-image-ref-point-y", iter->second.imageFill.yOffset, 
WPX_PERCENT);
           }
           else
           {
-            if (m_fillTransform.m_x0 != 0.0)
+            if (m_fillTransforms.getTranslateX() != 0.0)
             {
-              double xOffset = m_fillTransform.m_x0 / iter->second.imageFill.width;
+              double xOffset = m_fillTransforms.getTranslateX() / iter->second.imageFill.width;
               while (xOffset < 0.0)
                 xOffset += 1.0;
               while (xOffset > 1.0)
                 xOffset -= 1.0;
               propList.insert("draw:fill-image-ref-point-x", xOffset, WPX_PERCENT);
             }
-            if (m_fillTransform.m_y0 != 0.0)
+            if (m_fillTransforms.getTranslateY() != 0.0)
             {
-              double yOffset = m_fillTransform.m_y0 / iter->second.imageFill.width;
+              double yOffset = m_fillTransforms.getTranslateY() / iter->second.imageFill.width;
               while (yOffset < 0.0)
                 yOffset += 1.0;
               while (yOffset > 1.0)
@@ -763,8 +806,8 @@ void libcdr::CDRContentCollector::_fillProperties(WPXPropertyList &propList, WPX
             double scaleY = 1.0;
             if (iter->second.imageFill.flags & 0x04) // scale fill with image
             {
-              scaleX = sqrt(m_currentTransform.m_v0 * m_currentTransform.m_v0 + 
m_currentTransform.m_v1 * m_currentTransform.m_v1);
-              scaleY = sqrt(m_currentTransform.m_v3 * m_currentTransform.m_v3 + 
m_currentTransform.m_v4 * m_currentTransform.m_v4);
+              scaleX = m_currentTransforms.getScaleX();
+              scaleY = m_currentTransforms.getScaleY();
             }
             propList.insert("svg:width", iter->second.imageFill.width * scaleX);
             propList.insert("svg:height", iter->second.imageFill.height * scaleY);
@@ -774,23 +817,23 @@ void libcdr::CDRContentCollector::_fillProperties(WPXPropertyList &propList, 
WPX
           {
             if (iter->second.imageFill.xOffset != 0.0 && iter->second.imageFill.xOffset != 1.0)
               propList.insert("draw:fill-image-ref-point-x", iter->second.imageFill.xOffset, 
WPX_PERCENT);
-            if (iter->second.imageFill.yOffset != 0.0 && iter->second.imageFill.yOffset != 0.0)
+            if (iter->second.imageFill.yOffset != 0.0 && iter->second.imageFill.yOffset != 1.0)
               propList.insert("draw:fill-image-ref-point-y", iter->second.imageFill.yOffset, 
WPX_PERCENT);
           }
           else
           {
-            if (m_fillTransform.m_x0 != 0.0)
+            if (m_fillTransforms.getTranslateX() != 0.0)
             {
-              double xOffset = m_fillTransform.m_x0 / iter->second.imageFill.width;
+              double xOffset = m_fillTransforms.getTranslateX() / iter->second.imageFill.width;
               while (xOffset < 0.0)
                 xOffset += 1.0;
               while (xOffset > 1.0)
                 xOffset -= 1.0;
               propList.insert("draw:fill-image-ref-point-x", xOffset, WPX_PERCENT);
             }
-            if (m_fillTransform.m_y0 != 0.0)
+            if (m_fillTransforms.getTranslateY() != 0.0)
             {
-              double yOffset = m_fillTransform.m_y0 / iter->second.imageFill.width;
+              double yOffset = m_fillTransforms.getTranslateY() / iter->second.imageFill.width;
               while (yOffset < 0.0)
                 yOffset += 1.0;
               while (yOffset > 1.0)
@@ -839,8 +882,8 @@ void libcdr::CDRContentCollector::_lineProperties(WPXPropertyList &propList)
       double scale = 1.0;
       if (iter->second.lineType & 0x20) // scale line with image
       {
-        scale = sqrt(m_currentTransform.m_v0 * m_currentTransform.m_v0 + m_currentTransform.m_v1 * 
m_currentTransform.m_v1);
-        double scaleY = sqrt(m_currentTransform.m_v3 * m_currentTransform.m_v3 + 
m_currentTransform.m_v4 * m_currentTransform.m_v4);
+        scale = m_currentTransforms.getScaleX();
+        double scaleY = m_currentTransforms.getScaleY();
         if (scaleY > scale)
           scale = scaleY;
       }
@@ -1021,7 +1064,7 @@ void libcdr::CDRContentCollector::collectFillOpacity(double opacity)
 void libcdr::CDRContentCollector::collectBBox(double x0, double y0, double x1, double y1)
 {
   CDRBBox bBox(x0, y0, x1, y1);
-  if (m_currentVectLevel && m_page.width == 0.0 && m_page.width == 0.0)
+  if (m_currentVectLevel && m_page.width == 0.0 && m_page.height == 0.0)
   {
     m_page.width = bBox.getWidth();
     m_page.height = bBox.getHeight();
--- a/src/lib/CDRContentCollector.h
+++ b/src/lib/CDRContentCollector.h
@@ -62,7 +62,7 @@ public:
   void collectArcTo(double rx, double ry, bool largeArc, bool sweep, double x, double y);
   void collectClosePath();
   void collectLevel(unsigned level);
-  void collectTransform(double v0, double v1, double x, double v3, double v4, double y, bool 
considerGroupTransform);
+  void collectTransform(const CDRTransforms &transforms, bool considerGroupTransform);
   void collectFildId(unsigned id);
   void collectOutlId(unsigned id);
   void collectFild(unsigned, unsigned short, const CDRColor &, const CDRColor &, const CDRGradient 
&, const CDRImageFill &) {}
@@ -77,7 +77,7 @@ public:
   void collectBmp(unsigned, const std::vector<unsigned char>&) {}
   void collectBmpf(unsigned, unsigned, unsigned, const std::vector<unsigned char> &) {}
   void collectPpdt(const std::vector<std::pair<double, double> > &points, const 
std::vector<unsigned> &knotVector);
-  void collectFillTransform(double v0, double v1, double x, double v3, double v4, double y);
+  void collectFillTransform(const CDRTransforms &fillTrafo);
   void collectFillOpacity(double opacity);
   void collectPolygon();
   void collectSpline();
@@ -124,7 +124,8 @@ private:
   CDRBBox m_currentBBox;
 
   CDRPath m_currentPath;
-  CDRTransform m_currentTransform, m_fillTransform;
+  CDRTransforms m_currentTransforms;
+  CDRTransforms m_fillTransforms;
   CDRPolygon *m_polygon;
   bool m_isInPolygon;
   bool m_isInSpline;
@@ -132,7 +133,7 @@ private:
   std::stack<CDROutputElementList> m_contentOutputElements;
   std::stack<CDROutputElementList> m_fillOutputElements;
   std::stack<unsigned> m_groupLevels;
-  std::stack<CDRTransform> m_groupTransforms;
+  std::stack<CDRTransforms> m_groupTransforms;
   CDRSplineData m_splineData;
   double m_fillOpacity;
 
--- a/src/lib/CDRDocumentStructure.h
+++ b/src/lib/CDRDocumentStructure.h
@@ -53,6 +53,7 @@
 #define FOURCC_clof 0x666f6c63
 #define FOURCC_clol 0x6c6f6c63
 #define FOURCC_cloo 0x6f6f6c63
+#define FOURCC_clpt 0x74706c63
 #define FOURCC_cmpr 0x72706d63
 #define FOURCC_cont 0x746e6f63
 #define FOURCC_CPng 0x676e5043
--- a/src/lib/CDRParser.cpp
+++ b/src/lib/CDRParser.cpp
@@ -113,7 +113,7 @@ bool libcdr::CDRParser::parseWaldo(WPXInputStream *input)
     unsigned i = 0;
     for (i = 0; i < 8; ++i)
       offsets.push_back(readU32(input));
-    /* unsigned char flag = */ readU8(input);
+    input->seek(1, WPX_SEEK_CUR);
     for (i = 0; i < 10; i++)
       offsets.push_back(readU32(input));
     input->seek(offsets[0], WPX_SEEK_SET);
@@ -171,12 +171,13 @@ bool libcdr::CDRParser::parseWaldo(WPXInputStream *input)
         if (iter7 != records7.end())
           input->seek(iter7->second.offset, WPX_SEEK_SET);
         input->seek(0x26, WPX_SEEK_CUR);
-        trafo.m_v0 = readFixedPoint(input);
-        trafo.m_v1 = readFixedPoint(input);
-        trafo.m_x0 = readFixedPoint(input) / 1000.0;
-        trafo.m_v3 = readFixedPoint(input);
-        trafo.m_v4 = readFixedPoint(input);
-        trafo.m_y0 = readFixedPoint(input) / 1000.0;
+        double v0 = readFixedPoint(input);
+        double v1 = readFixedPoint(input);
+        double v2 = readFixedPoint(input) / 1000.0;
+        double v3 = readFixedPoint(input);
+        double v4 = readFixedPoint(input);
+        double v5 = readFixedPoint(input) / 1000.0;
+        trafo = CDRTransform(v0, v1, v2, v3, v4, v5);
       }
       records1[iterVec->id] = WaldoRecordType1(iterVec->id, next, previous, child, parent, flags, 
x0, y0, x1, y1, trafo);
     }
@@ -281,9 +282,9 @@ bool libcdr::CDRParser::parseWaldoStructure(WPXInputStream *input, std::stack<Wa
       {
         m_collector->collectGroup(waldoStack.size());
         m_collector->collectSpnd(waldoStack.top().m_id);
-        m_collector->collectTransform(waldoStack.top().m_trafo.m_v0, 
waldoStack.top().m_trafo.m_v1, waldoStack.top().m_trafo.m_x0,
-                                      waldoStack.top().m_trafo.m_v3, 
waldoStack.top().m_trafo.m_v4, waldoStack.top().m_trafo.m_y0,
-                                      true);
+        CDRTransforms trafos;
+        trafos.append(waldoStack.top().m_trafo);
+        m_collector->collectTransform(trafos, true);
       }
       iter1 = records1.find(waldoStack.top().m_child);
       if (iter1 == records1.end())
@@ -373,8 +374,10 @@ void libcdr::CDRParser::readWaldoTrfd(WPXInputStream *input)
     v4 = readFixedPoint(input);
     y0 += readFixedPoint(input) / 1000.0;
   }
-  CDR_DEBUG_MSG(("CDRParser::readWaldoTrfd %f %f %f %f %f %f %i\n", v0, v1, x0, v3, v4, y0, 
m_version));
-  m_collector->collectTransform(v0, v1, x0, v3, v4, y0, m_version < 400);
+  CDR_DEBUG_MSG(("CDRParser::readWaldoTrfd %f %f %f %f %f %f %u\n", v0, v1, x0, v3, v4, y0, 
m_version));
+  CDRTransforms trafos;
+  trafos.append(v0, v1, x0, v3, v4, y0);
+  m_collector->collectTransform(trafos, m_version < 400);
 }
 
 void libcdr::CDRParser::readWaldoLoda(WPXInputStream *input, unsigned length)
@@ -459,7 +462,7 @@ bool libcdr::CDRParser::parseRecord(WPXInputStream *input, unsigned *blockLength
       else
         m_collector->collectOtherList();
     }
-    CDR_DEBUG_MSG(("Record: level %u %s, length: 0x%.8x (%i)\n", level, toFourCC(fourCC), length, 
length));
+    CDR_DEBUG_MSG(("Record: level %u %s, length: 0x%.8x (%u)\n", level, toFourCC(fourCC), length, 
length));
 
     if (fourCC == FOURCC_RIFF || fourCC == FOURCC_LIST)
     {
@@ -490,7 +493,7 @@ bool libcdr::CDRParser::parseRecord(WPXInputStream *input, unsigned *blockLength
         else
           m_precision = libcdr::PRECISION_32BIT;
       }
-      else if (listType == FOURCC_vect)
+      else if (listType == FOURCC_vect || listType == FOURCC_clpt)
         m_collector->collectVect(level);
 
       bool compressed = (listType == FOURCC_cmpr ? true : false);
@@ -1161,6 +1164,7 @@ void libcdr::CDRParser::readRectangle(WPXInputStream *input)
   }
   else
     m_collector->collectLineTo(0.0, 0.0);
+  m_collector->collectClosePath();
 }
 
 void libcdr::CDRParser::readEllipse(WPXInputStream *input)
@@ -1210,6 +1214,7 @@ void libcdr::CDRParser::readEllipse(WPXInputStream *input)
     m_collector->collectMoveTo(x0, y0);
     m_collector->collectArcTo(rx, ry, false, true, x1, y1);
     m_collector->collectArcTo(rx, ry, true, true, x0, y0);
+    m_collector->collectClosePath();
   }
 }
 
@@ -1491,6 +1496,7 @@ void libcdr::CDRParser::readTrfd(WPXInputStream *input, unsigned length)
   while (i<numOfArgs)
     argOffsets[i++] = readUnsigned(input);
 
+  CDRTransforms trafos;
   for (i=0; i < argOffsets.size(); i++)
   {
     input->seek(startPosition+argOffsets[i], WPX_SEEK_SET);
@@ -1525,7 +1531,7 @@ void libcdr::CDRParser::readTrfd(WPXInputStream *input, unsigned length)
         v4 = readFixedPoint(input);
         y0 = (double)readS32(input) / 1000.0;
       }
-      m_collector->collectTransform(v0, v1, x0, v3, v4, y0, m_version < 400);
+      trafos.append(v0, v1, x0, v3, v4, y0);
     }
     else if (tmpType == 0x10)
     {
@@ -1555,6 +1561,8 @@ void libcdr::CDRParser::readTrfd(WPXInputStream *input, unsigned length)
 #endif
     }
   }
+  if (!trafos.empty())
+    m_collector->collectTransform(trafos,m_version < 400);
   input->seek(startPosition+chunkLength, WPX_SEEK_SET);
 }
 
@@ -2094,7 +2102,12 @@ void libcdr::CDRParser::readBmp(WPXInputStream *input, unsigned length)
     input->seek(2, WPX_SEEK_CUR);
     unsigned short palettesize = readU16(input);
     for (unsigned short i = 0; i <palettesize; ++i)
-      palette.push_back(readU8(input) | (readU8(input) << 8) | (readU8(input) << 16));
+    {
+      unsigned b = readU8(input);
+      unsigned g = readU8(input);
+      unsigned r = readU8(input);
+      palette.push_back(b | (g << 8) | (r << 16));
+    }
   }
   std::vector<unsigned char> bitmap(bmpsize);
   unsigned long tmpNumBytesRead = 0;
@@ -2194,7 +2207,9 @@ void libcdr::CDRParser::readFtil(WPXInputStream *input, unsigned length)
   double v3 = readDouble(input);
   double v4 = readDouble(input);
   double y0 = readDouble(input) / 254000.0;
-  m_collector->collectFillTransform(v0, v1, x0, v3, v4, y0);
+  CDRTransforms fillTrafos;
+  fillTrafos.append(v0, v1, x0, v3, v4, y0);
+  m_collector->collectFillTransform(fillTrafos);
 }
 
 void libcdr::CDRParser::readVersion(WPXInputStream *input, unsigned length)
@@ -2340,24 +2355,18 @@ void libcdr::CDRParser::readStlt(WPXInputStream *input, unsigned length)
       return;
     unsigned numFills = readU32(input);
     CDR_DEBUG_MSG(("CDRParser::readStlt numFills 0x%x\n", numFills));
-    std::map<unsigned,unsigned> fills;
     unsigned i = 0;
     for (i=0; i<numFills; ++i)
     {
-      unsigned fillId = readU32(input);
-      input->seek(4, WPX_SEEK_CUR);
-      fills[fillId] = readU32(input);
+      input->seek(12, WPX_SEEK_CUR);
       if (m_version >= 1300)
         input->seek(48, WPX_SEEK_CUR);
     }
     unsigned numOutls = readU32(input);
     CDR_DEBUG_MSG(("CDRParser::readStlt numOutls 0x%x\n", numOutls));
-    std::map<unsigned,unsigned> outls;
     for (i=0; i<numOutls; ++i)
     {
-      unsigned outlId = readU32(input);
-      input->seek(4, WPX_SEEK_CUR);
-      outls[outlId] = readU32(input);
+      input->seek(12, WPX_SEEK_CUR);
     }
     unsigned numFonts = readU32(input);
     CDR_DEBUG_MSG(("CDRParser::readStlt numFonts 0x%x\n", numFonts));
@@ -2379,13 +2388,10 @@ void libcdr::CDRParser::readStlt(WPXInputStream *input, unsigned length)
         input->seek(20, WPX_SEEK_CUR);
     }
     unsigned numAligns = readU32(input);
-    std::map<unsigned, unsigned> aligns;
     CDR_DEBUG_MSG(("CDRParser::readStlt numAligns 0x%x\n", numAligns));
     for (i=0; i<numAligns; ++i)
     {
-      unsigned alignId = readU32(input);
-      input->seek(4, WPX_SEEK_CUR);
-      aligns[alignId] = readU32(input);
+      input->seek(12, WPX_SEEK_CUR);
     }
     unsigned numIntervals = readU32(input);
     CDR_DEBUG_MSG(("CDRParser::readStlt numIntervals 0x%x\n", numIntervals));
@@ -2469,22 +2475,6 @@ void libcdr::CDRParser::readStlt(WPXInputStream *input, unsigned length)
         CDR_DEBUG_MSG(("CDRParser::readStlt parsing styles\n"));
         unsigned num = readU32(input);
         CDR_DEBUG_MSG(("CDRParser::readStlt parsing styles num 0x%x\n", num));
-        unsigned asize = 0;
-        switch (num)
-        {
-        case 3:
-          asize = 48;
-          break;
-        case 2:
-          asize = 28;
-          break;
-        case 1:
-        default:
-          asize = 8;
-          break;
-        }
-        if (m_version <= 800 && num > 1 && !set11Flag)
-          asize -= 4;
         unsigned styleId = readU32(input);
         CDRStltRecord style;
         style.parentId = readU32(input);
@@ -2720,6 +2710,18 @@ void libcdr::CDRParser::readTxsm(WPXInputStream *input, unsigned length)
 #endif
 }
 
+void libcdr::CDRParser::_readX6StyleString(WPXInputStream *input, unsigned length, WPXString 
&styleString)
+{
+  std::vector<unsigned char> styleBuffer(length);
+  unsigned long numBytesRead = 0;
+  const unsigned char *tmpBuffer = input->read(length, numBytesRead);
+  if (numBytesRead)
+    memcpy(&styleBuffer[0], tmpBuffer, numBytesRead);
+  appendCharacters(styleString, styleBuffer);
+  CDR_DEBUG_MSG(("CDRParser::_readX6StyleString - styleString = \"%s\"\n", styleString.cstr()));
+}
+
+
 void libcdr::CDRParser::readTxsm16(WPXInputStream *input)
 {
 #ifndef DEBUG
@@ -2768,7 +2770,8 @@ void libcdr::CDRParser::readTxsm16(WPXInputStream *input)
     input->seek(1, WPX_SEEK_CUR);
 
     unsigned len2 = readU32(input);
-    input->seek(2*len2, WPX_SEEK_CUR);
+    WPXString styleString;
+    _readX6StyleString(input, 2*len2, styleString);
 
     unsigned numRecords = readU32(input);
 
@@ -2782,10 +2785,12 @@ void libcdr::CDRParser::readTxsm16(WPXInputStream *input)
       if (flag & 0x04)
       {
         lenN = readU32(input);
-        input->seek(2*lenN, WPX_SEEK_CUR);
+        styleString.clear();
+        _readX6StyleString(input, 2*lenN, styleString);
       }
       lenN = readU32(input);
-      input->seek(2*lenN, WPX_SEEK_CUR);
+      styleString.clear();
+      _readX6StyleString(input, 2*lenN, styleString);
     }
 
     std::map<unsigned, CDRCharacterStyle> charStyles;
@@ -2820,7 +2825,8 @@ void libcdr::CDRParser::readTxsm6(WPXInputStream *input)
   input->seek(0x28, WPX_SEEK_CUR);
   input->seek(48, WPX_SEEK_CUR);
   input->seek(4, WPX_SEEK_CUR);
-  /* unsigned stlId = */ readU32(input);
+  /* unsigned stlId = */
+  readU32(input);
   unsigned numSt = readU32(input);
   unsigned i = 0;
   for (; i<numSt; ++i)
@@ -2837,7 +2843,8 @@ void libcdr::CDRParser::readTxsm6(WPXInputStream *input)
 void libcdr::CDRParser::readTxsm5(WPXInputStream *input)
 {
   input->seek(10, WPX_SEEK_CUR);
-  /* unsigned stlId = */ readU16(input);
+  /* unsigned stlId = */
+  readU16(input);
   unsigned numSt = readU16(input);
   unsigned i = 0;
   for (; i<numSt; ++i)
@@ -2865,7 +2872,8 @@ void libcdr::CDRParser::readStyd(WPXInputStream *input)
   unsigned numOfArgs = readUnsigned(input);
   unsigned startOfArgs = readUnsigned(input);
   unsigned startOfArgTypes = readUnsigned(input);
-  /* unsigned parentId = */ readUnsigned(input);
+  /* unsigned parentId = */
+  readUnsigned(input);
   std::vector<unsigned> argOffsets(numOfArgs, 0);
   std::vector<unsigned> argTypes(numOfArgs, 0);
   unsigned i = 0;
diff --git a/src/lib/CDRParser.h b/src/lib/CDRParser.h
index 33797a1..967ed57 100644
--- a/src/lib/CDRParser.h
+++ b/src/lib/CDRParser.h
@@ -111,6 +111,8 @@ private:
 
   bool _redirectX6Chunk(WPXInputStream **input, unsigned &length);
 
+  void _readX6StyleString(WPXInputStream *input, unsigned length, WPXString &styleString);
+
   std::vector<WPXInputStream *> m_externalStreams;
 
   unsigned m_version;
diff --git a/src/lib/CDRPath.cpp b/src/lib/CDRPath.cpp
index 46b10d0..b7d42f2 100644
--- a/src/lib/CDRPath.cpp
+++ b/src/lib/CDRPath.cpp
@@ -45,6 +45,7 @@ public:
       m_y(y) {}
   ~CDRMoveToElement() {}
   void writeOut(WPXPropertyListVector &vec) const;
+  void transform(const CDRTransforms &trafos);
   void transform(const CDRTransform &trafo);
   CDRPathElement *clone();
 private:
@@ -60,6 +61,7 @@ public:
       m_y(y) {}
   ~CDRLineToElement() {}
   void writeOut(WPXPropertyListVector &vec) const;
+  void transform(const CDRTransforms &trafos);
   void transform(const CDRTransform &trafo);
   CDRPathElement *clone();
 private:
@@ -79,6 +81,7 @@ public:
       m_y(y) {}
   ~CDRCubicBezierToElement() {}
   void writeOut(WPXPropertyListVector &vec) const;
+  void transform(const CDRTransforms &trafos);
   void transform(const CDRTransform &trafo);
   CDRPathElement *clone();
 private:
@@ -100,6 +103,7 @@ public:
       m_y(y) {}
   ~CDRQuadraticBezierToElement() {}
   void writeOut(WPXPropertyListVector &vec) const;
+  void transform(const CDRTransforms &trafos);
   void transform(const CDRTransform &trafo);
   CDRPathElement *clone();
 private:
@@ -116,22 +120,13 @@ public:
     : m_points(points) {}
   ~CDRSplineToElement() {}
   void writeOut(WPXPropertyListVector &vec) const;
+  void transform(const CDRTransforms &trafos);
   void transform(const CDRTransform &trafo);
   CDRPathElement *clone();
 private:
   std::vector<std::pair<double, double> > m_points;
 };
 
-class CDRClosePathElement : public CDRPathElement
-{
-public:
-  CDRClosePathElement() {}
-  ~CDRClosePathElement() {}
-  void writeOut(WPXPropertyListVector &vec) const;
-  void transform(const CDRTransform &trafo);
-  CDRPathElement *clone();
-};
-
 class CDRArcToElement : public CDRPathElement
 {
 public:
@@ -145,6 +140,7 @@ public:
       m_y(y) {}
   ~CDRArcToElement() {}
   void writeOut(WPXPropertyListVector &vec) const;
+  void transform(const CDRTransforms &trafos);
   void transform(const CDRTransform &trafo);
   CDRPathElement *clone();
 private:
@@ -169,6 +165,11 @@ void libcdr::CDRMoveToElement::writeOut(WPXPropertyListVector &vec) const
   vec.append(node);
 }
 
+void libcdr::CDRMoveToElement::transform(const CDRTransforms &trafos)
+{
+  trafos.applyToPoint(m_x,m_y);
+}
+
 void libcdr::CDRMoveToElement::transform(const CDRTransform &trafo)
 {
   trafo.applyToPoint(m_x,m_y);
@@ -188,6 +189,11 @@ void libcdr::CDRLineToElement::writeOut(WPXPropertyListVector &vec) const
   vec.append(node);
 }
 
+void libcdr::CDRLineToElement::transform(const CDRTransforms &trafos)
+{
+  trafos.applyToPoint(m_x,m_y);
+}
+
 void libcdr::CDRLineToElement::transform(const CDRTransform &trafo)
 {
   trafo.applyToPoint(m_x,m_y);
@@ -211,6 +217,13 @@ void libcdr::CDRCubicBezierToElement::writeOut(WPXPropertyListVector &vec) 
const
   vec.append(node);
 }
 
+void libcdr::CDRCubicBezierToElement::transform(const CDRTransforms &trafos)
+{
+  trafos.applyToPoint(m_x1,m_y1);
+  trafos.applyToPoint(m_x2,m_y2);
+  trafos.applyToPoint(m_x,m_y);
+}
+
 void libcdr::CDRCubicBezierToElement::transform(const CDRTransform &trafo)
 {
   trafo.applyToPoint(m_x1,m_y1);
@@ -234,6 +247,12 @@ void libcdr::CDRQuadraticBezierToElement::writeOut(WPXPropertyListVector &vec) 
c
   vec.append(node);
 }
 
+void libcdr::CDRQuadraticBezierToElement::transform(const CDRTransforms &trafos)
+{
+  trafos.applyToPoint(m_x1,m_y1);
+  trafos.applyToPoint(m_x,m_y);
+}
+
 void libcdr::CDRQuadraticBezierToElement::transform(const CDRTransform &trafo)
 {
   trafo.applyToPoint(m_x1,m_y1);
@@ -297,6 +316,13 @@ void libcdr::CDRSplineToElement::writeOut(WPXPropertyListVector &vec) const
   vec.append(node);
 }
 
+void libcdr::CDRSplineToElement::transform(const CDRTransforms &trafos)
+{
+  for (std::vector<std::pair<double, double> >::iterator iter = m_points.begin();
+       iter != m_points.end(); ++iter)
+    trafos.applyToPoint(iter->first, iter->second);
+}
+
 void libcdr::CDRSplineToElement::transform(const CDRTransform &trafo)
 {
   for (std::vector<std::pair<double, double> >::iterator iter = m_points.begin();
@@ -323,6 +349,11 @@ void libcdr::CDRArcToElement::writeOut(WPXPropertyListVector &vec) const
   vec.append(node);
 }
 
+void libcdr::CDRArcToElement::transform(const CDRTransforms &trafos)
+{
+  trafos.applyToArc(m_rx, m_ry, m_rotation, m_sweep, m_x, m_y);
+}
+
 void libcdr::CDRArcToElement::transform(const CDRTransform &trafo)
 {
   trafo.applyToArc(m_rx, m_ry, m_rotation, m_sweep, m_x, m_y);
@@ -333,22 +364,6 @@ libcdr::CDRPathElement *libcdr::CDRArcToElement::clone()
   return new CDRArcToElement(m_rx, m_ry, m_rotation, m_largeArc, m_sweep, m_x, m_y);
 }
 
-void libcdr::CDRClosePathElement::writeOut(WPXPropertyListVector &vec) const
-{
-  WPXPropertyList node;
-  node.insert("libwpg:path-action", "Z");
-  vec.append(node);
-}
-
-void libcdr::CDRClosePathElement::transform(const CDRTransform & /* trafo */)
-{
-}
-
-libcdr::CDRPathElement *libcdr::CDRClosePathElement::clone()
-{
-  return new CDRClosePathElement();
-}
-
 void libcdr::CDRPath::appendMoveTo(double x, double y)
 {
   m_elements.push_back(new libcdr::CDRMoveToElement(x, y));
@@ -381,13 +396,14 @@ void libcdr::CDRPath::appendSplineTo(std::vector<std::pair<double, double> > 
&po
 
 void libcdr::CDRPath::appendClosePath()
 {
-  m_elements.push_back(new libcdr::CDRClosePathElement());
+  m_isClosed = true;
 }
 
-libcdr::CDRPath::CDRPath(const libcdr::CDRPath &path) : m_elements()
+libcdr::CDRPath::CDRPath(const libcdr::CDRPath &path) : m_elements(), m_isClosed(false)
 {
   for (std::vector<CDRPathElement *>::const_iterator iter = path.m_elements.begin(); iter != 
path.m_elements.end(); ++iter)
     m_elements.push_back((*iter)->clone());
+  m_isClosed = path.isClosed();
 }
 
 libcdr::CDRPath::~CDRPath()
@@ -407,6 +423,12 @@ void libcdr::CDRPath::writeOut(WPXPropertyListVector &vec) const
     (*iter)->writeOut(vec);
 }
 
+void libcdr::CDRPath::transform(const CDRTransforms &trafos)
+{
+  for (std::vector<CDRPathElement *>::iterator iter = m_elements.begin(); iter != 
m_elements.end(); ++iter)
+    (*iter)->transform(trafos);
+}
+
 void libcdr::CDRPath::transform(const CDRTransform &trafo)
 {
   for (std::vector<CDRPathElement *>::iterator iter = m_elements.begin(); iter != 
m_elements.end(); ++iter)
@@ -424,11 +446,17 @@ void libcdr::CDRPath::clear()
     if (*iter)
       delete(*iter);
   m_elements.clear();
+  m_isClosed = false;
 }
 
-bool libcdr::CDRPath::empty()
+bool libcdr::CDRPath::empty() const
 {
   return m_elements.empty();
 }
 
+bool libcdr::CDRPath::isClosed() const
+{
+  return m_isClosed;
+}
+
 /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
--- a/src/lib/CDRPath.h
+++ b/src/lib/CDRPath.h
@@ -38,12 +38,15 @@
 namespace libcdr
 {
 
+class CDRTransform;
+
 class CDRPathElement
 {
 public:
   CDRPathElement() {}
   virtual ~CDRPathElement() {}
   virtual void writeOut(WPXPropertyListVector &vec) const = 0;
+  virtual void transform(const CDRTransforms &trafos) = 0;
   virtual void transform(const CDRTransform &trafo) = 0;
   virtual CDRPathElement *clone() = 0;
 };
@@ -52,7 +55,7 @@ public:
 class CDRPath : public CDRPathElement
 {
 public:
-  CDRPath() : m_elements() {}
+  CDRPath() : m_elements(), m_isClosed(false) {}
   CDRPath(const CDRPath &path);
   ~CDRPath();
 
@@ -66,14 +69,20 @@ public:
   void appendPath(const CDRPath &path);
 
   void writeOut(WPXPropertyListVector &vec) const;
+  void transform(const CDRTransforms &trafos);
   void transform(const CDRTransform &trafo);
   CDRPathElement *clone();
 
   void clear();
-  bool empty();
+  bool empty() const;
+  bool isClosed() const;
+
+private:
+  CDRPath &operator=(const CDRPath &path);
 
 private:
   std::vector<CDRPathElement *> m_elements;
+  bool m_isClosed;
 };
 
 } // namespace libcdr
--- a/src/lib/CDRSVGGenerator.cpp
+++ b/src/lib/CDRSVGGenerator.cpp
@@ -107,13 +107,12 @@ void libcdr::CDRSVGGenerator::setStyle(const ::WPXPropertyList &propList, 
const
   m_gradient = gradient;
   if(m_style["draw:shadow"] && m_style["draw:shadow"]->getStr() == "visible")
   {
-    unsigned shadowColour = 0;
     double shadowRed = 0.0;
     double shadowGreen = 0.0;
     double shadowBlue = 0.0;
     if (m_style["draw:shadow-color"])
     {
-      shadowColour = stringToColour(m_style["draw:shadow-color"]->getStr());
+      unsigned shadowColour = stringToColour(m_style["draw:shadow-color"]->getStr());
       shadowRed = (double)((shadowColour & 0x00ff0000) >> 16)/255.0;
       shadowGreen = (double)((shadowColour & 0x0000ff00) >> 8)/255.0;
       shadowBlue = (double)(shadowColour & 0x000000ff)/255.0;
--- a/src/lib/CDRStringVector.cpp
+++ b/src/lib/CDRStringVector.cpp
@@ -36,7 +36,6 @@ class CDRStringVectorImpl
 {
 public:
   CDRStringVectorImpl() : m_strings() {}
-  CDRStringVectorImpl(const CDRStringVectorImpl &impl) : m_strings(impl.m_strings) {}
   ~CDRStringVectorImpl() {}
   std::vector<WPXString> m_strings;
 };
@@ -55,10 +54,14 @@ libcdr::CDRStringVector::CDRStringVector(const CDRStringVector &vec)
 
 libcdr::CDRStringVector::~CDRStringVector()
 {
+  delete m_pImpl;
 }
 
 libcdr::CDRStringVector &libcdr::CDRStringVector::operator=(const CDRStringVector &vec)
 {
+  // Check for self-assignment
+  if (this == &vec)
+    return *this;
   if (m_pImpl)
     delete m_pImpl;
   m_pImpl = new CDRStringVectorImpl(*(vec.m_pImpl));
--- a/src/lib/CDRStylesCollector.h
+++ b/src/lib/CDRStylesCollector.h
@@ -63,7 +63,7 @@ public:
   void collectArcTo(double, double, bool, bool, double, double) {}
   void collectClosePath() {}
   void collectLevel(unsigned) {}
-  void collectTransform(double, double, double, double, double, double, bool) {}
+  void collectTransform(const CDRTransforms &, bool) {}
   void collectFildId(unsigned) {}
   void collectOutlId(unsigned) {}
   void collectFild(unsigned id, unsigned short fillType, const CDRColor &color1, const CDRColor 
&color2, const CDRGradient &gradient, const CDRImageFill &imageFill);
@@ -79,7 +79,7 @@ public:
   void collectBmp(unsigned imageId, const std::vector<unsigned char> &bitmap);
   void collectBmpf(unsigned patternId, unsigned width, unsigned height, const std::vector<unsigned 
char> &pattern);
   void collectPpdt(const std::vector<std::pair<double, double> > &, const std::vector<unsigned> &) 
{}
-  void collectFillTransform(double, double, double, double, double, double) {}
+  void collectFillTransform(const CDRTransforms &) {}
   void collectFillOpacity(double) {}
   void collectPolygon() {}
   void collectSpline() {}
--- /dev/null
+++ b/src/lib/CDRTransforms.cpp
@@ -0,0 +1,314 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* libcdr
+ * Version: MPL 1.1 / GPLv2+ / LGPLv2+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Major Contributor(s):
+ * Copyright (C) 2012 Fridrich Strba <fridrich.strba@bluewin.ch>
+ * Copyright (C) 2011 Eilidh McAdam <tibbylickle@gmail.com>
+ *
+ *
+ * All Rights Reserved.
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
+ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
+ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
+ * instead of those above.
+ */
+
+#include "CDRTransforms.h"
+#include "CDRPath.h"
+#include "libcdr_utils.h"
+
+
+libcdr::CDRTransform::CDRTransform()
+  : m_v0(1.0), m_v1(0.0), m_x0(0.0),
+    m_v3(0.0), m_v4(1.0), m_y0(0.0)
+{
+}
+
+libcdr::CDRTransform::CDRTransform(double v0, double v1, double x0, double v3, double v4, double 
y0)
+  : m_v0(v0), m_v1(v1), m_x0(x0), m_v3(v3), m_v4(v4), m_y0(y0)
+{
+}
+
+libcdr::CDRTransform::CDRTransform(const CDRTransform &trafo)
+  : m_v0(trafo.m_v0), m_v1(trafo.m_v1), m_x0(trafo.m_x0),
+    m_v3(trafo.m_v3), m_v4(trafo.m_v4), m_y0(trafo.m_y0) {}
+
+
+void libcdr::CDRTransform::applyToPoint(double &x, double &y) const
+{
+  double tmpX = m_v0*x + m_v1*y+m_x0;
+  y = m_v3*x + m_v4*y+m_y0;
+  x = tmpX;
+}
+
+void libcdr::CDRTransform::applyToArc(double &rx, double &ry, double &rotation, bool &sweep, 
double &x, double &y) const
+{
+  // First transform the end-point, which is the easiest
+  applyToPoint(x, y);
+
+  // represent ellipse as a transformed unit circle
+  double v0 = m_v0*rx*cos(rotation) - m_v1*rx*sin(rotation);
+  double v1 = m_v1*ry*cos(rotation) + m_v0*ry*sin(rotation);
+  double v3 = m_v3*rx*cos(rotation) - m_v4*rx*sin(rotation);
+  double v4 = m_v4*ry*cos(rotation) + m_v3*ry*sin(rotation);
+
+  // centered implicit equation
+  double A = v0*v0 + v1*v1;
+  double C = v3*v3 + v4*v4;
+  double B = 2.0*(v0*v3  +  v1*v4);
+
+  double r1, r2;
+  // convert implicit equation to angle and halfaxis:
+  if (CDR_ALMOST_ZERO(B))
+  {
+    rotation = 0;
+    r1 = A;
+    r2 = C;
+  }
+  else
+  {
+    if (CDR_ALMOST_ZERO(A-C))
+    {
+      r1 = A + B / 2.0;
+      r2 = A - B / 2.0;
+      rotation = M_PI / 4.0;
+    }
+    else
+    {
+      double radical = 1.0 + B*B /((A-C)*(A-C));
+      radical = radical < 0.0 ? 0.0 : sqrt (radical);
+
+      r1 = (A+C + radical*(A-C)) / 2.0;
+      r2 = (A+C - radical*(A-C)) / 2.0;
+      rotation = atan2(B,(A-C)) / 2.0;
+    }
+  }
+
+  // Prevent sqrt of a negative number, however small it might be.
+  r1 = r1 < 0.0 ? 0.0 : sqrt(r1);
+  r2 = r2 < 0.0 ? 0.0 : sqrt(r2);
+
+  // now r1 and r2 are half-axis:
+  if ((A-C) <= 0)
+  {
+    ry = r1;
+    rx = r2;
+  }
+  else
+  {
+    ry = r2;
+    rx = r1;
+  }
+
+  // sweep is inversed each time the arc is flipped
+  sweep = (m_v0*m_v4 < m_v3*m_v1);
+}
+
+double libcdr::CDRTransform::_getScaleX() const
+{
+  double x0 = 0.0;
+  double x1 = 1.0;
+  double y0 = 0.0;
+  double y1 = 0.0;
+  applyToPoint(x0, y0);
+  applyToPoint(x1, y1);
+  return x1 - x0;
+}
+
+double libcdr::CDRTransform::getScaleX() const
+{
+  return fabs(_getScaleX());
+}
+
+bool libcdr::CDRTransform::getFlipX() const
+{
+  return (0 > _getScaleX());
+}
+
+double libcdr::CDRTransform::_getScaleY() const
+{
+  double x0 = 0.0;
+  double x1 = 0.0;
+  double y0 = 0.0;
+  double y1 = 1.0;
+  applyToPoint(x0, y0);
+  applyToPoint(x1, y1);
+  return y1 - y0;
+}
+
+double libcdr::CDRTransform::getScaleY() const
+{
+  return fabs(_getScaleY());
+}
+
+bool libcdr::CDRTransform::getFlipY() const
+{
+  return (0 > _getScaleY());
+}
+
+double libcdr::CDRTransform::getRotation() const
+{
+  double x0 = 0.0;
+  double x1 = 1.0;
+  double y0 = 0.0;
+  double y1 = 0.0;
+  applyToPoint(x0, y0);
+  applyToPoint(x1, y1);
+  double angle = atan2(y1-y0, x1-x0);
+  if (angle < 0.0)
+    angle += 2*M_PI;
+  return angle;
+}
+
+double libcdr::CDRTransform::getTranslateX() const
+{
+  double x = 0.0;
+  double y = 0.0;
+  applyToPoint(x, y);
+  return x;
+}
+
+double libcdr::CDRTransform::getTranslateY() const
+{
+  double x = 0.0;
+  double y = 0.0;
+  applyToPoint(x, y);
+  return y;
+}
+
+
+libcdr::CDRTransforms::CDRTransforms()
+  : m_trafos()
+{
+}
+
+libcdr::CDRTransforms::CDRTransforms(const CDRTransforms &trafos)
+  : m_trafos(trafos.m_trafos)
+{
+}
+
+libcdr::CDRTransforms::~CDRTransforms()
+{
+}
+
+void libcdr::CDRTransforms::append(double v0, double v1, double x0, double v3, double v4, double 
y0)
+{
+  append(CDRTransform(v0, v1, x0, v3, v4, y0));
+}
+
+void libcdr::CDRTransforms::append(const CDRTransform &trafo)
+{
+  m_trafos.push_back(trafo);
+}
+
+void libcdr::CDRTransforms::clear()
+{
+  m_trafos.clear();
+}
+
+bool libcdr::CDRTransforms::empty() const
+{
+  return m_trafos.empty();
+}
+
+void libcdr::CDRTransforms::applyToPoint(double &x, double &y) const
+{
+  for (std::vector<CDRTransform>::const_iterator iter = m_trafos.begin(); iter != m_trafos.end(); 
++iter)
+    iter->applyToPoint(x,y);
+}
+
+void libcdr::CDRTransforms::applyToArc(double &rx, double &ry, double &rotation, bool &sweep, 
double &x, double &y) const
+{
+  for (std::vector<CDRTransform>::const_iterator iter = m_trafos.begin(); iter != m_trafos.end(); 
++iter)
+    iter->applyToArc(rx, ry, rotation, sweep, x, y);
+}
+
+double libcdr::CDRTransforms::_getScaleX() const
+{
+  double x0 = 0.0;
+  double x1 = 1.0;
+  double y0 = 0.0;
+  double y1 = 0.0;
+  applyToPoint(x0, y0);
+  applyToPoint(x1, y1);
+  return x1 - x0;
+}
+
+double libcdr::CDRTransforms::getScaleX() const
+{
+  return fabs(_getScaleX());
+}
+
+bool libcdr::CDRTransforms::getFlipX() const
+{
+  return (0 > _getScaleX());
+}
+
+double libcdr::CDRTransforms::_getScaleY() const
+{
+  double x0 = 0.0;
+  double x1 = 0.0;
+  double y0 = 0.0;
+  double y1 = 1.0;
+  applyToPoint(x0, y0);
+  applyToPoint(x1, y1);
+  return y1 - y0;
+}
+
+double libcdr::CDRTransforms::getScaleY() const
+{
+  return fabs(_getScaleY());
+}
+
+bool libcdr::CDRTransforms::getFlipY() const
+{
+  return (0 > _getScaleY());
+}
+
+double libcdr::CDRTransforms::getRotation() const
+{
+  double x0 = 0.0;
+  double x1 = 1.0;
+  double y0 = 0.0;
+  double y1 = 0.0;
+  applyToPoint(x0, y0);
+  applyToPoint(x1, y1);
+  double angle = atan2(y1-y0, x1-x0);
+  if (angle < 0.0)
+    angle += 2*M_PI;
+  return angle;
+}
+
+double libcdr::CDRTransforms::getTranslateX() const
+{
+  double x = 0.0;
+  double y = 0.0;
+  applyToPoint(x, y);
+  return x;
+}
+
+double libcdr::CDRTransforms::getTranslateY() const
+{
+  double x = 0.0;
+  double y = 0.0;
+  applyToPoint(x, y);
+  return y;
+}
+
+
+/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
--- /dev/null
+++ b/src/lib/CDRTransforms.h
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* libcdr
+ * Version: MPL 1.1 / GPLv2+ / LGPLv2+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Major Contributor(s):
+ * Copyright (C) 2012 Fridrich Strba <fridrich.strba@bluewin.ch>
+ *
+ * All Rights Reserved.
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
+ * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
+ * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
+ * instead of those above.
+ */
+
+#ifndef __CDRTRANSFORMS_H__
+#define __CDRTRANSFORMS_H__
+
+#include <vector>
+#include <math.h>
+
+namespace libcdr
+{
+class CDRPath;
+
+class CDRTransform
+{
+public:
+  CDRTransform();
+  CDRTransform(double v0, double v1, double x0, double v3, double v4, double y0);
+  CDRTransform(const CDRTransform &trafo);
+
+  void applyToPoint(double &x, double &y) const;
+  void applyToArc(double &rx, double &ry, double &rotation, bool &sweep, double &x, double &y) 
const;
+  double getScaleX() const;
+  double getScaleY() const;
+  double getRotation() const;
+  double getTranslateX() const;
+  double getTranslateY() const;
+  bool getFlipX() const;
+  bool getFlipY() const;
+
+private:
+  double _getScaleX() const;
+  double _getScaleY() const;
+  double m_v0;
+  double m_v1;
+  double m_x0;
+  double m_v3;
+  double m_v4;
+  double m_y0;
+};
+
+class CDRTransforms
+{
+public:
+  CDRTransforms();
+  CDRTransforms(const CDRTransforms &trafos);
+  ~CDRTransforms();
+
+  void append(double v0, double v1, double x0, double v3, double v4, double y0);
+  void append(const CDRTransform &trafo);
+  void clear();
+  bool empty() const;
+
+  void applyToPoint(double &x, double &y) const;
+  void applyToArc(double &rx, double &ry, double &rotation, bool &sweep, double &x, double &y) 
const;
+  double getScaleX() const;
+  double getScaleY() const;
+  double getRotation() const;
+  double getTranslateX() const;
+  double getTranslateY() const;
+  bool getFlipX() const;
+  bool getFlipY() const;
+
+private:
+  double _getScaleX() const;
+  double _getScaleY() const;
+  std::vector<CDRTransform> m_trafos;
+};
+
+} // namespace libcdr
+
+#endif /* __CDRTRANSFORMS_H__ */
+/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
--- a/src/lib/CDRTypes.cpp
+++ b/src/lib/CDRTypes.cpp
@@ -32,76 +32,6 @@
 #include "CDRPath.h"
 #include "libcdr_utils.h"
 
-void libcdr::CDRTransform::applyToPoint(double &x, double &y) const
-{
-  double tmpX = m_v0*x + m_v1*y+m_x0;
-  y = m_v3*x + m_v4*y+m_y0;
-  x = tmpX;
-}
-
-void libcdr::CDRTransform::applyToArc(double &rx, double &ry, double &rotation, bool &sweep, 
double &x, double &y) const
-{
-  // First transform the end-point, which is the easiest
-  applyToPoint(x, y);
-
-  // represent ellipse as a transformed unit circle
-  double v0 = m_v0*rx*cos(rotation) - m_v1*rx*sin(rotation);
-  double v1 = m_v1*ry*cos(rotation) + m_v0*ry*sin(rotation);
-  double v3 = m_v3*rx*cos(rotation) - m_v4*rx*sin(rotation);
-  double v4 = m_v4*ry*cos(rotation) + m_v3*ry*sin(rotation);
-
-  // centered implicit equation
-  double A = v0*v0 + v1*v1;
-  double C = v3*v3 + v4*v4;
-  double B = 2.0*(v0*v3  +  v1*v4);
-
-  double r1, r2;
-  // convert implicit equation to angle and halfaxis:
-  if (CDR_ALMOST_ZERO(B))
-  {
-    rotation = 0;
-    r1 = A;
-    r2 = C;
-  }
-  else
-  {
-    if (CDR_ALMOST_ZERO(A-C))
-    {
-      r1 = A + B / 2.0;
-      r2 = A - B / 2.0;
-      rotation = M_PI / 4.0;
-    }
-    else
-    {
-      double radical = 1.0 + B*B /((A-C)*(A-C));
-      radical = radical < 0.0 ? 0.0 : sqrt (radical);
-
-      r1 = (A+C + radical*(A-C)) / 2.0;
-      r2 = (A+C - radical*(A-C)) / 2.0;
-      rotation = atan2(B,(A-C)) / 2.0;
-    }
-  }
-
-  // Prevent sqrt of a negative number, however small it might be.
-  r1 = r1 < 0.0 ? 0.0 : sqrt(r1);
-  r2 = r2 < 0.0 ? 0.0 : sqrt(r2);
-
-  // now r1 and r2 are half-axis:
-  if ((A-C) <= 0)
-  {
-    ry = r1;
-    rx = r2;
-  }
-  else
-  {
-    ry = r2;
-    rx = r1;
-  }
-
-  // sweep is inversed each time the arc is flipped
-  sweep = (m_v0*m_v4 < m_v3*m_v1);
-}
-
 void libcdr::CDRPolygon::create(libcdr::CDRPath &path) const
 {
   libcdr::CDRPath tmpPath(path);
--- a/src/lib/CDRTypes.h
+++ b/src/lib/CDRTypes.h
@@ -32,29 +32,12 @@
 #include <vector>
 #include <math.h>
 #include <libwpd/libwpd.h>
+#include "CDRTransforms.h"
 
 namespace libcdr
 {
 class CDRPath;
 
-struct CDRTransform
-{
-  double m_v0;
-  double m_v1;
-  double m_x0;
-  double m_v3;
-  double m_v4;
-  double m_y0;
-  CDRTransform()
-    : m_v0(1.0), m_v1(0.0), m_x0(0.0),
-      m_v3(0.0), m_v4(1.0), m_y0(0.0) {}
-  CDRTransform(double v0, double v1, double x0, double v3, double v4, double y0)
-    : m_v0(v0), m_v1(v1), m_x0(x0), m_v3(v3), m_v4(v4), m_y0(y0) {}
-
-  void applyToPoint(double &x, double &y) const;
-  void applyToArc(double &rx, double &ry, double &rotation, bool &sweep, double &x, double &y) 
const;
-};
-
 struct CDRBBox
 {
   double m_x;
@@ -63,8 +46,6 @@ struct CDRBBox
   double m_h;
   CDRBBox()
     : m_x(0.0), m_y(0.0), m_w(0.0), m_h(0.0) {}
-  CDRBBox(const CDRBBox &box)
-    : m_x(box.m_x), m_y(box.m_y), m_w(box.m_w), m_h(box.m_h) {}
   CDRBBox(double x0, double y0, double x1, double y1)
     : m_x(x0 < x1 ? x0 : x1), m_y(y0 < y1 ? y0 : y1), m_w(fabs(x1-x0)), m_h(fabs(y1-y0)) {}
   double getWidth() const
@@ -93,8 +74,6 @@ struct CDRColor
   CDRColor() : m_colorModel(0), m_colorValue(0) {}
   CDRColor(unsigned short colorModel, unsigned colorValue)
     : m_colorModel(colorModel), m_colorValue(colorValue) {}
-  CDRColor(const CDRColor &color)
-    : m_colorModel(color.m_colorModel), m_colorValue(color.m_colorValue) {}
 };
 
 struct CDRGradientStop
@@ -104,8 +83,6 @@ struct CDRGradientStop
   CDRGradientStop() : m_color(), m_offset(0.0) {}
   CDRGradientStop(const CDRColor &color, double offset)
     : m_color(color), m_offset(offset) {}
-  CDRGradientStop(const CDRGradientStop &stop)
-    : m_color(stop.m_color), m_offset(stop.m_offset) {}
 };
 
 struct CDRGradient
@@ -120,10 +97,6 @@ struct CDRGradient
   std::vector<CDRGradientStop> m_stops;
   CDRGradient()
     : m_type(0), m_mode(0), m_angle(0.0), m_midPoint(0.0), m_edgeOffset(0), m_centerXOffset(0), 
m_centerYOffset(0), m_stops() {}
-  CDRGradient(const CDRGradient &gradient)
-    : m_type(gradient.m_type), m_mode(gradient.m_mode), m_angle(gradient.m_angle), 
m_midPoint(gradient.m_midPoint),
-      m_edgeOffset(gradient.m_edgeOffset), m_centerXOffset(gradient.m_centerXOffset), 
m_centerYOffset(gradient.m_centerYOffset),
-      m_stops(gradient.m_stops) {}
 };
 
 struct CDRImageFill
@@ -152,8 +125,6 @@ struct CDRFillStyle
     : fillType(0), color1(), color2(), gradient(), imageFill() {}
   CDRFillStyle(unsigned short ft, CDRColor c1, CDRColor c2, const CDRGradient &gr, const 
CDRImageFill &img)
     : fillType(ft), color1(c1), color2(c2), gradient(gr), imageFill(img) {}
-  CDRFillStyle(const CDRFillStyle &style)
-    : fillType(style.fillType), color1(style.color1), color2(style.color2), 
gradient(style.gradient), imageFill(style.imageFill) {}
 };
 
 struct CDRLineStyle
@@ -265,8 +236,6 @@ struct CDRPage
   CDRPage() : width(0.0), height(0.0), offsetX(0.0), offsetY(0.0) {}
   CDRPage(double w, double h, double ox, double oy)
     : width(w), height(h), offsetX(ox), offsetY(oy) {}
-  CDRPage(const CDRPage &page)
-    : width(page.width), height(page.height), offsetX(page.offsetX), offsetY(page.offsetY) {}
 };
 
 struct CDRSplineData
@@ -276,8 +245,6 @@ struct CDRSplineData
   CDRSplineData() : points(), knotVector() {}
   CDRSplineData(const std::vector<std::pair<double, double> > &ps, const std::vector<unsigned> 
&kntv)
     : points(ps), knotVector(kntv) {}
-  CDRSplineData(const CDRSplineData &data)
-    : points(data.points), knotVector(data.knotVector) {}
   void clear()
   {
     points.clear();
@@ -304,17 +271,12 @@ struct WaldoRecordType1
 {
   WaldoRecordType1(unsigned id, unsigned short next, unsigned short previous,
                    unsigned short child, unsigned short parent, unsigned short flags,
-                   double x0, double y0, double x1, double y1, const CDRTransform trafo)
+                   double x0, double y0, double x1, double y1, const CDRTransform &trafo)
     : m_id(id), m_next(next), m_previous(previous), m_child(child), m_parent(parent),
       m_flags(flags), m_x0(x0), m_y0(y0), m_x1(x1), m_y1(y1), m_trafo(trafo) {}
   WaldoRecordType1()
     : m_id(0), m_next(0), m_previous(0), m_child(0), m_parent(0), m_flags(0),
       m_x0(0.0), m_y0(0.0), m_x1(0.0), m_y1(0.0), m_trafo() {}
-  WaldoRecordType1(const WaldoRecordType1 &record)
-    : m_id(record.m_id), m_next(record.m_next), m_previous(record.m_previous),
-      m_child(record.m_child), m_parent(record.m_parent), m_flags(record.m_flags),
-      m_x0(record.m_x0), m_y0(record.m_y0), m_x1(record.m_x1), m_y1(record.m_y1),
-      m_trafo(record.m_trafo) {}
   unsigned m_id;
   unsigned short m_next;
   unsigned short m_previous;
@@ -333,8 +295,6 @@ struct CDRCMYKColor
   CDRCMYKColor(unsigned colorValue, bool percentage = true);
   CDRCMYKColor(double cyan, double magenta, double yellow, double black)
     : c(cyan), m(magenta), y(yellow), k(black) {}
-  CDRCMYKColor(const CDRCMYKColor &color)
-    : c(color.c), m(color.m), y(color.y), k(color.k) {}
   ~CDRCMYKColor() {}
   double c;
   double m;
@@ -349,8 +309,6 @@ struct CDRRGBColor
   CDRRGBColor(unsigned colorValue);
   CDRRGBColor(double red, double green, double blue)
     : r(red), g(green), b(blue) {}
-  CDRRGBColor(const CDRRGBColor &color)
-    : r(color.r), g(color.g), b(color.b) {}
   ~CDRRGBColor() {}
   double r;
   double g;
@@ -364,8 +322,6 @@ struct CDRLab2Color
   CDRLab2Color(unsigned colorValue);
   CDRLab2Color(double l, double A, double B)
     : L(l), a(A), b(B) {}
-  CDRLab2Color(const CDRLab2Color &color)
-    : L(color.L), a(color.a), b(color.b) {}
   ~CDRLab2Color() {}
   double L;
   double a;
@@ -379,8 +335,6 @@ struct CDRLab4Color
   CDRLab4Color(unsigned colorValue);
   CDRLab4Color(double l, double A, double B)
     : L(l), a(A), b(B) {}
-  CDRLab4Color(const CDRLab2Color &color)
-    : L(color.L), a(color.a), b(color.b) {}
   ~CDRLab4Color() {}
   double L;
   double a;
--- a/src/lib/CDRZipStream.cpp
+++ b/src/lib/CDRZipStream.cpp
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <zlib.h>
 #include <map>
+#include <libwpd-stream/libwpd-stream.h>
 #include "CDRZipStream.h"
 #include "CDRInternalStream.h"
 #include "libcdr_utils.h"
@@ -159,7 +160,12 @@ WPXInputStream *libcdr::CDRZipStream::getDocumentOLEStream(const char *name)
 
 bool libcdr::CDRZipStreamImpl::findCentralDirectoryEnd()
 {
-  m_input->seek(m_cdir_offset, WPX_SEEK_SET);
+#if defined(LIBWPD_STREAM_VERSION_MAJOR) && defined(LIBWPD_STREAM_VERSION_MINOR) && 
defined(LIBWPD_STREAM_VERSION_REVISION) \
+  && (LIBWPD_STREAM_VERSION_MAJOR > 0 || (LIBWPD_STREAM_VERSION_MAJOR == 0 && 
(LIBWPD_STREAM_VERSION_MINOR > 9 \
+  || (LIBWPD_STREAM_VERSION_MINOR == 9 && LIBWPD_STREAM_VERSION_REVISION >= 5))))
+  if (m_cdir_offset || m_input->seek(-1024, WPX_SEEK_END))
+#endif
+    m_input->seek(m_cdir_offset, WPX_SEEK_SET);
   try
   {
     while (!m_input->atEOS())
--- a/src/lib/CMXParser.cpp
+++ b/src/lib/CMXParser.cpp
@@ -97,7 +97,7 @@ bool libcdr::CMXParser::parseRecord(WPXInputStream *input, unsigned level)
     unsigned length = readU32(input);
     long endPosition = input->tell() + length;
 
-    CDR_DEBUG_MSG(("Record: level %u %s, length: 0x%.8x (%i)\n", level, toFourCC(fourCC), length, 
length));
+    CDR_DEBUG_MSG(("Record: level %u %s, length: 0x%.8x (%u)\n", level, toFourCC(fourCC), length, 
length));
 
     if (fourCC == FOURCC_RIFF || fourCC == FOURCC_RIFX || fourCC == FOURCC_LIST)
     {
@@ -191,7 +191,7 @@ void libcdr::CMXParser::readCMXHeader(WPXInputStream *input)
     tmpString.append((char)readU8(input));
   CDR_DEBUG_MSG(("CMX Version Minor: %s\n", tmpString.cstr()));
   m_unit = readU16(input, m_bigEndian);
-  CDR_DEBUG_MSG(("CMX Base Units: %i\n", m_unit));
+  CDR_DEBUG_MSG(("CMX Base Units: %u\n", m_unit));
   m_scale = readDouble(input, m_bigEndian);
   CDR_DEBUG_MSG(("CMX Units Scale: %.9f\n", m_scale));
   input->seek(12, WPX_SEEK_CUR);
@@ -297,13 +297,13 @@ void libcdr::CMXParser::readPage(WPXInputStream *input, unsigned length)
 
 void libcdr::CMXParser::readBeginPage(WPXInputStream *input)
 {
-  unsigned char tagId = 0;
-  unsigned short tagLength = 0;
   CDRBBox box;
   CDRTransform matrix;
   unsigned flags = 0;
   if (m_precision == libcdr::PRECISION_32BIT)
   {
+    unsigned char tagId = 0;
+    unsigned short tagLength = 0;
     do
     {
       long startOffset = input->tell();
@@ -314,7 +314,7 @@ void libcdr::CMXParser::readBeginPage(WPXInputStream *input)
         break;
       }
       tagLength = readU16(input, m_bigEndian);
-      CDR_DEBUG_MSG(("  CMXParser::readBeginPage - tagId %i, tagLength %i\n", tagId, tagLength));
+      CDR_DEBUG_MSG(("  CMXParser::readBeginPage - tagId %i, tagLength %u\n", tagId, tagLength));
       switch (tagId)
       {
       case CMX_Tag_BeginPage_PageSpecification:
@@ -353,13 +353,13 @@ void libcdr::CMXParser::readBeginGroup(WPXInputStream * /* input */)
 
 void libcdr::CMXParser::readPolyCurve(WPXInputStream *input)
 {
-  unsigned char tagId = 0;
-  unsigned short tagLength = 0;
   unsigned pointNum = 0;
   std::vector<std::pair<double, double> > points;
   std::vector<unsigned char> pointTypes;
   if (m_precision == libcdr::PRECISION_32BIT)
   {
+    unsigned char tagId = 0;
+    unsigned short tagLength = 0;
     do
     {
       long startOffset = input->tell();
@@ -370,7 +370,7 @@ void libcdr::CMXParser::readPolyCurve(WPXInputStream *input)
         break;
       }
       tagLength = readU16(input, m_bigEndian);
-      CDR_DEBUG_MSG(("  CMXParser::readPolyCurve - tagId %i, tagLength %i\n", tagId, tagLength));
+      CDR_DEBUG_MSG(("  CMXParser::readPolyCurve - tagId %i, tagLength %u\n", tagId, tagLength));
       switch (tagId)
       {
       case CMX_Tag_PolyCurve_RenderingAttr:
@@ -418,8 +418,6 @@ void libcdr::CMXParser::readPolyCurve(WPXInputStream *input)
 
 void libcdr::CMXParser::readEllipse(WPXInputStream *input)
 {
-  unsigned char tagId = 0;
-  unsigned short tagLength = 0;
   double angle1 = 0.0;
   double angle2 = 0.0;
   double rotation = 0.0;
@@ -432,6 +430,8 @@ void libcdr::CMXParser::readEllipse(WPXInputStream *input)
 
   if (m_precision == libcdr::PRECISION_32BIT)
   {
+    unsigned char tagId = 0;
+    unsigned short tagLength = 0;
     do
     {
       long startOffset = input->tell();
@@ -442,7 +442,7 @@ void libcdr::CMXParser::readEllipse(WPXInputStream *input)
         break;
       }
       tagLength = readU16(input, m_bigEndian);
-      CDR_DEBUG_MSG(("  CMXParser::readEllipse - tagId %i, tagLength %i\n", tagId, tagLength));
+      CDR_DEBUG_MSG(("  CMXParser::readEllipse - tagId %i, tagLength %u\n", tagId, tagLength));
       switch (tagId)
       {
       case CMX_Tag_Ellips_RenderingAttr:
@@ -518,8 +518,6 @@ void libcdr::CMXParser::readEllipse(WPXInputStream *input)
 
 void libcdr::CMXParser::readRectangle(WPXInputStream *input)
 {
-  unsigned char tagId = 0;
-  unsigned short tagLength = 0;
   double cx = 0.0;
   double cy = 0.0;
   double width = 0.0;
@@ -528,6 +526,8 @@ void libcdr::CMXParser::readRectangle(WPXInputStream *input)
   double angle = 0.0;
   if (m_precision == libcdr::PRECISION_32BIT)
   {
+    unsigned char tagId = 0;
+    unsigned short tagLength = 0;
     do
     {
       long startOffset = input->tell();
@@ -538,7 +538,7 @@ void libcdr::CMXParser::readRectangle(WPXInputStream *input)
         break;
       }
       tagLength = readU16(input, m_bigEndian);
-      CDR_DEBUG_MSG(("  CMXParser::readRectangle - tagId %i, tagLength %i\n", tagId, tagLength));
+      CDR_DEBUG_MSG(("  CMXParser::readRectangle - tagId %i, tagLength %u\n", tagId, tagLength));
       switch (tagId)
       {
       case CMX_Tag_Rectangle_RenderingAttr:
@@ -608,13 +608,15 @@ libcdr::CDRTransform libcdr::CMXParser::readMatrix(WPXInputStream *input)
   switch (type)
   {
   case 2: // general matrix
-    matrix.m_v0 = readDouble(input, m_bigEndian);
-    matrix.m_v3 = readDouble(input, m_bigEndian);
-    matrix.m_v1 = readDouble(input, m_bigEndian);
-    matrix.m_v4 = readDouble(input, m_bigEndian);
-    matrix.m_x0 = readDouble(input, m_bigEndian);
-    matrix.m_y0 = readDouble(input, m_bigEndian);
-    return matrix;
+  {
+    double v0 = readDouble(input, m_bigEndian);
+    double v3 = readDouble(input, m_bigEndian);
+    double v1 = readDouble(input, m_bigEndian);
+    double v4 = readDouble(input, m_bigEndian);
+    double x0 = readDouble(input, m_bigEndian);
+    double y0 = readDouble(input, m_bigEndian);
+    return libcdr::CDRTransform(v0, v1, x0, v3, v4, y0);
+  }
   default: // identity matrix for the while
     return matrix;
   }
@@ -649,7 +651,7 @@ void libcdr::CMXParser::readFill(WPXInputStream *input)
           CDR_DEBUG_MSG(("    Solid fill - tagId %i\n", tagId));
         }
         tagLength = readU16(input, m_bigEndian);
-        CDR_DEBUG_MSG(("    Solid fill - tagId %i, tagLength %i\n", tagId, tagLength));
+        CDR_DEBUG_MSG(("    Solid fill - tagId %i, tagLength %u\n", tagId, tagLength));
         switch (tagId)
         {
         case CMX_Tag_RenderAttr_FillSpec_Uniform:
@@ -707,7 +709,7 @@ void libcdr::CMXParser::readRenderingAttributes(WPXInputStream *input)
           break;
         }
         tagLength = readU16(input, m_bigEndian);
-        CDR_DEBUG_MSG(("  Fill specification - tagId %i, tagLength %i\n", tagId, tagLength));
+        CDR_DEBUG_MSG(("  Fill specification - tagId %i, tagLength %u\n", tagId, tagLength));
         switch (tagId)
         {
 
@@ -735,7 +737,7 @@ void libcdr::CMXParser::readRenderingAttributes(WPXInputStream *input)
           break;
         }
         tagLength = readU16(input, m_bigEndian);
-        CDR_DEBUG_MSG(("  Outline specification - tagId %i, tagLength %i\n", tagId, tagLength));
+        CDR_DEBUG_MSG(("  Outline specification - tagId %i, tagLength %u\n", tagId, tagLength));
         switch (tagId)
         {
         case CMX_Tag_RenderAttr_OutlineSpec:
@@ -765,7 +767,7 @@ void libcdr::CMXParser::readRenderingAttributes(WPXInputStream *input)
           break;
         }
         tagLength = readU16(input, m_bigEndian);
-        CDR_DEBUG_MSG(("  Lens specification - tagId %i, tagLength %i\n", tagId, tagLength));
+        CDR_DEBUG_MSG(("  Lens specification - tagId %i, tagLength %u\n", tagId, tagLength));
         switch (tagId)
         {
         default:
@@ -790,7 +792,7 @@ void libcdr::CMXParser::readRenderingAttributes(WPXInputStream *input)
           break;
         }
         tagLength = readU16(input, m_bigEndian);
-        CDR_DEBUG_MSG(("  Canvas specification - tagId %i, tagLength %i\n", tagId, tagLength));
+        CDR_DEBUG_MSG(("  Canvas specification - tagId %i, tagLength %u\n", tagId, tagLength));
         switch (tagId)
         {
         default:
@@ -815,7 +817,7 @@ void libcdr::CMXParser::readRenderingAttributes(WPXInputStream *input)
           break;
         }
         tagLength = readU16(input, m_bigEndian);
-        CDR_DEBUG_MSG(("  Container specification - tagId %i, tagLength %i\n", tagId, tagLength));
+        CDR_DEBUG_MSG(("  Container specification - tagId %i, tagLength %u\n", tagId, tagLength));
         switch (tagId)
         {
         default:
@@ -830,10 +832,10 @@ void libcdr::CMXParser::readRenderingAttributes(WPXInputStream *input)
 
 void libcdr::CMXParser::readJumpAbsolute(WPXInputStream *input)
 {
-  unsigned char tagId = 0;
-  unsigned short tagLength = 0;
   if (m_precision == libcdr::PRECISION_32BIT)
   {
+    unsigned char tagId = 0;
+    unsigned short tagLength = 0;
     do
     {
       long endOffset = input->tell() + tagLength;
@@ -844,7 +846,7 @@ void libcdr::CMXParser::readJumpAbsolute(WPXInputStream *input)
         break;
       }
       tagLength = readU16(input, m_bigEndian);
-      CDR_DEBUG_MSG(("  CMXParser::readJumpAbsolute - tagId %i, tagLength %i\n", tagId, 
tagLength));
+      CDR_DEBUG_MSG(("  CMXParser::readJumpAbsolute - tagId %i, tagLength %u\n", tagId, 
tagLength));
       switch (tagId)
       {
       case CMX_Tag_JumpAbsolute_Offset:
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -28,6 +28,7 @@ libcdr_@CDR_MAJOR_VERSION@_@CDR_MINOR_VERSION@_la_SOURCES = \
        CDRStringVector.cpp \
        CDRStylesCollector.cpp \
        CDRSVGGenerator.cpp \
+       CDRTransforms.cpp \
        CDRTypes.cpp \
        CDRZipStream.cpp \
        CMXDocument.cpp \
@@ -45,6 +46,7 @@ libcdr_@CDR_MAJOR_VERSION@_@CDR_MINOR_VERSION@_la_SOURCES = \
        CDRPath.h \
        CDRStylesCollector.h \
        CDRSVGGenerator.h \
+       CDRTransforms.h \
        CDRTypes.h \
        CDRZipStream.h \
        CMXDocumentStructure.h \
--- a/src/lib/libcdr_utils.cpp
+++ b/src/lib/libcdr_utils.cpp
@@ -14,7 +14,6 @@
  *
  * Major Contributor(s):
  * Copyright (C) 2012 Fridrich Strba <fridrich.strba@bluewin.ch>
- * Copyright (C) 2011 Eilidh McAdam <tibbylickle@gmail.com>
  *
  *
  * All Rights Reserved.
--- a/src/lib/libcdr_utils.h
+++ b/src/lib/libcdr_utils.h
@@ -49,6 +49,7 @@
 
 typedef unsigned char uint8_t;
 typedef unsigned short uint16_t;
+typedef short int16_t;
 typedef unsigned uint32_t;
 typedef int int32_t;
 typedef unsigned __int64 uint64_t;
--- a/src/lib/makefile.mk
+++ b/src/lib/makefile.mk
@@ -49,6 +49,7 @@ SLOFILES= \
     $(SLO)$/CDRStringVector.obj \
     $(SLO)$/CDRStylesCollector.obj \
     $(SLO)$/CDRSVGGenerator.obj \
+    $(SLO)$/CDRTransforms.obj \
     $(SLO)$/CDRTypes.obj \
     $(SLO)$/CDRZipStream.obj \
     $(SLO)$/CMXDocument.obj \

Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.