[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    koffice/plugins/pathshapes/enhancedpath
From:       Jan Hambrecht <jaham () gmx ! net>
Date:       2010-03-09 22:43:02
Message-ID: 1268174582.801128.24647.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 1101341 by jaham:

make viewbox transformation more robust and also enable mirroring



 M  +18 -23    EnhancedPathCommand.cpp  
 M  +52 -57    EnhancedPathShape.cpp  
 M  +17 -13    EnhancedPathShape.h  


--- trunk/koffice/plugins/pathshapes/enhancedpath/EnhancedPathCommand.cpp \
#1101340:1101341 @@ -58,22 +58,20 @@
     case 'M':
         if (!pointsCount)
             return false;
-        m_parent->moveTo(m_parent->viewboxToShape(points[0]));
+        m_parent->moveTo(points[0]);
         if (pointsCount > 1)
             for (int i = 1; i < pointsCount; i++)
-                m_parent->lineTo(m_parent->viewboxToShape(points[i]));
+                m_parent->lineTo(points[i]);
         break;
     // line from current point (x y) +
     case 'L':
         foreach(const QPointF &point, points)
-            m_parent->lineTo(m_parent->viewboxToShape(point));
+            m_parent->lineTo(point);
         break;
     // cubic bezier curve from current point (x1 y1 x2 y2 x y) +
     case 'C':
         for (int i = 0; i < pointsCount; i+=3)
-            m_parent->curveTo(m_parent->viewboxToShape(points[i]),
-                               m_parent->viewboxToShape(points[i+1]),
-                               m_parent->viewboxToShape(points[i+2]));
+            m_parent->curveTo(points[i], points[i+1], points[i+2]);
         break;
     // closes the current subpath
     case 'Z':
@@ -98,16 +96,16 @@
         bool lineTo = m_command.unicode() == 'T';
 
         for (int i = 0; i < pointsCount; i+=3) {
-            const QPointF &radii = m_parent->viewboxToShape(points[i+1]);
+            const QPointF &radii = points[i+1];
             const QPointF &angles = points[i+2] / rad2deg;
             // compute the ellipses starting point
             QPointF start(radii.x() * cos(angles.x()), radii.y() * sin(angles.x()));
             qreal sweepAngle = degSweepAngle(points[i+2].x(), points[i+2].y(), \
false);  
             if (lineTo)
-                m_parent->lineTo(m_parent->viewboxToShape(points[i]) + start);
+                m_parent->lineTo(points[i] + start);
             else
-                m_parent->moveTo(m_parent->viewboxToShape(points[i]) + start);
+                m_parent->moveTo(points[i] + start);
 
             m_parent->arcTo(radii.x(), radii.y(), points[i+2].x(), sweepAngle);
         }
@@ -122,8 +120,8 @@
         for (int i = 0; i < pointsCount; i+=4) {
             QRectF bbox = rectFromPoints(points[i], points[i+1]);
             QPointF center = bbox.center();
-            qreal rx = 0.5 * m_parent->viewboxToShape(bbox.width());
-            qreal ry = 0.5 * m_parent->viewboxToShape(bbox.height());
+            qreal rx = 0.5 * bbox.width();
+            qreal ry = 0.5 * bbox.height();
             qreal startAngle = angleFromPoint(points[i+2] - center);
             qreal stopAngle = angleFromPoint(points[i+3] - center);
             // we are moving counter-clockwise to the end angle
@@ -132,9 +130,9 @@
             QPointF startPoint(rx * cos(startAngle), ry * sin(2*M_PI - startAngle));
 
             if (lineTo)
-                m_parent->lineTo(m_parent->viewboxToShape(center) + startPoint);
+                m_parent->lineTo(center + startPoint);
             else
-                m_parent->moveTo(m_parent->viewboxToShape(center) + startPoint);
+                m_parent->moveTo(center + startPoint);
 
             m_parent->arcTo(rx, ry, startAngle * rad2deg, sweepAngle * rad2deg);
         }
@@ -149,17 +147,17 @@
         for (int i = 0; i < pointsCount; i+=4) {
             QRectF bbox = rectFromPoints(points[i], points[i+1]);
             QPointF center = bbox.center();
-            qreal rx = 0.5 * m_parent->viewboxToShape(bbox.width());
-            qreal ry = 0.5 * m_parent->viewboxToShape(bbox.height());
+            qreal rx = 0.5 * bbox.width();
+            qreal ry = 0.5 * bbox.height();
             qreal startAngle = angleFromPoint(points[i+2] - center);
             qreal stopAngle = angleFromPoint(points[i+3] - center);
             // we are moving clockwise to the end angle
             qreal sweepAngle = radSweepAngle(startAngle, stopAngle, true);
 
             if (lineTo)
-                m_parent->lineTo(m_parent->viewboxToShape(points[i+2]));
+                m_parent->lineTo(points[i+2]);
             else
-                m_parent->moveTo(m_parent->viewboxToShape(points[i+2]));
+                m_parent->moveTo(points[i+2]);
 
             m_parent->arcTo(rx, ry, startAngle * rad2deg, sweepAngle * rad2deg);
         }
@@ -168,8 +166,7 @@
     // elliptical quadrant (initial segment tangential to x-axis) (x y) +
     case 'X': {
         KoPathPoint * lastPoint = lastPathPoint();
-        foreach (QPointF point, points) {
-            point = m_parent->viewboxToShape(point);
+        foreach (const QPointF &point, points) {
             qreal rx = point.x() - lastPoint->point().x();
             qreal ry = point.y() - lastPoint->point().y();
             qreal startAngle = ry > 0.0 ? 90.0 : 270.0;
@@ -181,8 +178,7 @@
     // elliptical quadrant (initial segment tangential to y-axis) (x y) +
     case 'Y': {
         KoPathPoint * lastPoint = lastPathPoint();
-        foreach (QPointF point, points) {
-            point = m_parent->viewboxToShape(point);
+        foreach (const QPointF &point, points) {
             qreal rx = point.x() - lastPoint->point().x();
             qreal ry = point.y() - lastPoint->point().y();
             qreal startAngle = rx < 0.0 ? 0.0 : 180.0;
@@ -194,8 +190,7 @@
     // quadratic bezier curve (x1 y1 x y)+
     case 'Q':
         for (int i = 0; i < pointsCount; i+=2)
-            m_parent->curveTo(m_parent->viewboxToShape(points[i]),
-                               m_parent->viewboxToShape(points[i+1]));
+            m_parent->curveTo(points[i], points[i+1]);
         break;
     default:
         break;
--- trunk/koffice/plugins/pathshapes/enhancedpath/EnhancedPathShape.cpp \
#1101340:1101341 @@ -1,5 +1,5 @@
 /* This file is part of the KDE project
- * Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
+ * Copyright (C) 2007,2010 Jan Hambrecht <jaham@gmx.net>
  * Copyright (C) 2009-2010 Thomas Zander <zander@kde.org>
  *
  * This library is free software; you can redistribute it and/or
@@ -30,6 +30,7 @@
 #include <KoShapeSavingContext.h>
 #include <KoUnit.h>
 #include <KoOdfWorkaround.h>
+#include <KoPathPoint.h>
 
 EnhancedPathShape::EnhancedPathShape(const QRectF &viewBox)
 : m_viewBox(viewBox), m_viewBoxOffset(0.0, 0.0), m_mirrorVertically(false), \
m_mirrorHorizontally(false) @@ -64,7 +65,6 @@
     EnhancedPathHandle *handle = m_enhancedHandles[ handleId ];
     if (handle) {
         handle->changePosition(shapeToViewbox(point));
-        evaluateHandles();
     }
 }
 
@@ -75,42 +75,73 @@
     foreach (EnhancedPathCommand *cmd, m_commands)
         cmd->execute();
 
+    m_viewBound = outline().boundingRect();
+
+    QMatrix matrix;
+    matrix.translate(m_viewBoxOffset.x(), m_viewBoxOffset.y());
+    matrix = m_viewMatrix * matrix;
+
+    KoSubpathList::const_iterator pathIt(m_subpaths.constBegin());
+    for (; pathIt != m_subpaths.constEnd(); ++pathIt) {
+        KoSubpath::const_iterator it((*pathIt)->constBegin());
+        for (; it != (*pathIt)->constEnd(); ++it) {
+            (*it)->map(matrix);
+        }
+    }
+    const int handleCount = m_enhancedHandles.count();
+    QList<QPointF> handles;
+    for (int i = 0; i < handleCount; ++i)
+        handles.append(matrix.map(m_enhancedHandles[i]->position()));
+    setHandles(handles);
+
     normalize();
 }
 
 void EnhancedPathShape::setSize(const QSizeF &newSize)
 {
-    QMatrix matrix(resizeMatrix(newSize));
-
     KoParameterShape::setSize(newSize);
 
-    qreal scaleX = matrix.m11();
-    qreal scaleY = matrix.m22();
-    m_viewBoxOffset.rx() *= scaleX;
-    m_viewBoxOffset.ry() *= scaleY;
-    m_viewMatrix.scale(scaleX, scaleY);
+    // calculate scaling factors from viewbox size to shape size
+    qreal xScale = newSize.width()/m_viewBound.width();
+    qreal yScale = newSize.height()/m_viewBound.height();
 
-    setMirroring();
+    // create view matrix, take mirroring into account
+    m_viewMatrix.reset();
+    m_viewMatrix.translate(m_viewBound.center().x(), m_viewBound.center().y());
+    m_viewMatrix.scale(m_mirrorHorizontally ? -xScale : xScale, m_mirrorVertically ? \
-yScale : yScale); +    m_viewMatrix.translate(-m_viewBound.center().x(), \
-m_viewBound.center().y()); +
+    updatePath(newSize);
 }
 
-
 QPointF EnhancedPathShape::normalize()
 {
-    QPointF offset = KoPathShape::normalize();
+    QPointF offset = KoParameterShape::normalize();
+
     m_viewBoxOffset -= offset;
 
     return offset;
 }
 
+QPointF EnhancedPathShape::shapeToViewbox(const QPointF &point) const
+{
+    return m_viewMatrix.inverted().map( point-m_viewBoxOffset );
+}
+
 void EnhancedPathShape::evaluateHandles()
 {
     const int handleCount = m_enhancedHandles.count();
     QList<QPointF> handles;
     for (int i = 0; i < handleCount; ++i)
-        handles.append(viewboxToShape(m_enhancedHandles[i]->position()));
+        handles.append(m_enhancedHandles[i]->position());
     setHandles(handles);
 }
 
+QRectF EnhancedPathShape::viewBox() const
+{
+    return m_viewBox;
+}
+
 qreal EnhancedPathShape::evaluateReference(const QString &reference)
 {
     if (reference.isEmpty())
@@ -290,27 +321,6 @@
         updatePath(size());
 }
 
-const QRectF & EnhancedPathShape::viewBox() const
-{
-    return m_viewBox;
-}
-
-QPointF EnhancedPathShape::shapeToViewbox(const QPointF &point) const
-{
-    //NOTE: m_flipMatrix doesn't need to be inverted since when we flip twice the \
                efect of the flip is inverted.
-    return m_viewMatrix.inverted().map( m_flipMatrix.map(point)-m_viewBoxOffset );
-}
-
-QPointF EnhancedPathShape::viewboxToShape(const QPointF &point) const
-{
-    return m_flipMatrix.map(m_viewMatrix.map(point) + m_viewBoxOffset);
-}
-
-qreal EnhancedPathShape::viewboxToShape(qreal value) const
-{
-    return m_flipMatrix.map(m_viewMatrix.map(QPointF(value, value))).x();
-}
-
 void EnhancedPathShape::saveOdf(KoShapeSavingContext &context) const
 {
     if (isParametricShape()) {
@@ -367,9 +377,6 @@
                 addModifiers(modifiers);
             }
 
-            setMirrorHorizontally( child.attributeNS(KoXmlNS::draw, \
                "mirror-horizontal") == "true");
-            setMirrorVertically( child.attributeNS(KoXmlNS::draw, "mirror-vertical") \
                == "true");
-
             KoXmlElement grandChild;
             forEachElement(grandChild, child) {
                 if (grandChild.namespaceURI() != KoXmlNS::draw)
@@ -397,21 +404,22 @@
             if (!path.isEmpty()) {
                 parsePathData(path);
             }
+
+            setMirrorHorizontally( child.attributeNS(KoXmlNS::draw, \
"mirror-horizontal") == "true"); +            setMirrorVertically( \
child.attributeNS(KoXmlNS::draw, "mirror-vertical") == "true");  }
     }
 
-    QPointF pos;
-    pos.setX(KoUnit::parseValue(element.attributeNS(KoXmlNS::svg, "x", QString())));
-    pos.setY(KoUnit::parseValue(element.attributeNS(KoXmlNS::svg, "y", QString())));
-    setPosition(pos);
-    normalize();
-
     QSizeF size;
     size.setWidth(KoUnit::parseValue(element.attributeNS(KoXmlNS::svg, "width", \
                QString())));
     size.setHeight(KoUnit::parseValue(element.attributeNS(KoXmlNS::svg, "height", \
                QString())));
-
     setSize(size);
 
+    QPointF pos;
+    pos.setX(KoUnit::parseValue(element.attributeNS(KoXmlNS::svg, "x", QString())));
+    pos.setY(KoUnit::parseValue(element.attributeNS(KoXmlNS::svg, "y", QString())));
+    setPosition(pos);
+
     loadOdfAttributes(element, context, OdfMandatories | OdfTransformation | \
OdfAdditionalAttributes | OdfCommonChildElements);  
     return true;
@@ -451,7 +459,6 @@
 {
     if( m_mirrorHorizontally != mirrorHorizontally) {
         m_mirrorHorizontally = mirrorHorizontally;
-//         setMirroring();
     }
 }
 
@@ -459,17 +466,5 @@
 {
     if( m_mirrorVertically != mirrorVertically) {
         m_mirrorVertically = mirrorVertically;
-//         setMirroring();
     }
 }
-
-void EnhancedPathShape::setMirroring()
-{
-    qreal centerX = size().width() * 0.5;
-    qreal centerY = size().height() * 0.5;
-
-    m_flipMatrix.reset();
-    m_flipMatrix.translate(centerX, centerY);
-    m_flipMatrix.scale(m_mirrorHorizontally? -1.0 : 1.0, m_mirrorVertically? -1.0 : \
                1.0);
-    m_flipMatrix.translate(-centerX, -centerY);
-}
--- trunk/koffice/plugins/pathshapes/enhancedpath/EnhancedPathShape.h \
#1101340:1101341 @@ -1,5 +1,5 @@
 /* This file is part of the KDE project
- * Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net>
+ * Copyright (C) 2007,2010 Jan Hambrecht <jaham@gmx.net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -47,7 +47,7 @@
 {
 public:
     explicit EnhancedPathShape(const QRectF &viewBox);
-    ~EnhancedPathShape();
+    virtual ~EnhancedPathShape();
 
     /**
      * Evaluates the given reference to a identifier, modifier or formula.
@@ -73,17 +73,21 @@
 
     /// Add formula with given name and textual represenation
     void addFormula(const QString &name, const QString &formula);
+
     /// Add a single handle with format: x y minX maxX minY maxY
     void addHandle(const QMap<QString,QVariant> &handle);
+
     /// Add modifiers with format: modifier0 modifier1 modifier2 ...
     void addModifiers(const QString &modifiers);
+
     /// Add command for instance "M 0 0"
     void addCommand(const QString &command);
+
     /// Returns the viewbox of the enhanced path shape
-    const QRectF & viewBox() const;
+    QRectF viewBox() const;
+
+    /// Converts from shape coordinates to viewbox coordinates
     QPointF shapeToViewbox(const QPointF &point) const;
-    QPointF viewboxToShape(const QPointF &point) const;
-    qreal viewboxToShape(qreal value) const;
 
     /// Sets if the shape is to be mirrored horizontally before aplying any other \
                transformations
     //NOTE: in the standard nothing is mentioned about the priorities of the \
transformations" @@ -99,12 +103,14 @@
     EnhancedPathParameter *parameter(const QString &text);
 
 protected:
-    void saveOdf(KoShapeSavingContext &context) const;
+    // from KoShape
+    virtual void saveOdf(KoShapeSavingContext &context) const;
+    // from KoShape
     virtual bool loadOdf(const KoXmlElement &element, KoShapeLoadingContext \
&context);  // from KoParameterShape
-    void moveHandleAction(int handleId, const QPointF &point, Qt::KeyboardModifiers \
modifiers = Qt::NoModifier); +    virtual void moveHandleAction(int handleId, const \
QPointF &point, Qt::KeyboardModifiers modifiers = Qt::NoModifier);  // from \
                KoParameterShape
-    void updatePath(const QSizeF &size);
+    virtual void updatePath(const QSizeF &size);
 private:
 
     void evaluateHandles();
@@ -116,15 +122,13 @@
     /// Adds a new command
     void addCommand(const QString &command, bool triggerUpdate);
 
-    void setMirroring();
-
     typedef QMap<QString, EnhancedPathFormula*> FormulaStore;
     typedef QList<qreal> ModifierStore;
     typedef QMap<QString, EnhancedPathParameter*> ParameterStore;
 
-    QRectF m_viewBox;
-    QMatrix m_viewMatrix;
-    QMatrix m_flipMatrix;
+    QRectF m_viewBox;     ///< the viewbox rectangle
+    QRectF m_viewBound;   ///< the bounding box of the path in viewbox coordinates
+    QMatrix m_viewMatrix; ///< matrix to convert from viewbox coordinates to shape \
coordinates  QPointF m_viewBoxOffset;
     QList<EnhancedPathCommand*> m_commands; ///< the commands creating the outline
     QList<EnhancedPathHandle*> m_enhancedHandles; ///< the handles for modifiying \
the shape


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic