[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