KHTML
PathQt.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "config.h"
00030 #include "Path.h"
00031
00032 #include "FloatRect.h"
00033
00034 #include "AffineTransform.h"
00035 #include <QPainterPath>
00036 #include <QMatrix>
00037 #include <QString>
00038
00039 #define _USE_MATH_DEFINES
00040 #include <math.h>
00041
00042 namespace WebCore {
00043
00044 Path::Path()
00045 : m_path(new QPainterPath())
00046 {
00047 }
00048
00049 Path::~Path()
00050 {
00051 delete m_path;
00052 }
00053
00054 Path::Path(const Path& other)
00055 : m_path(new QPainterPath(*other.platformPath()))
00056 {
00057 }
00058
00059 Path& Path::operator=(const Path& other)
00060 {
00061 if (&other != this) {
00062 delete m_path;
00063 m_path = new QPainterPath(*other.platformPath());
00064 }
00065
00066 return *this;
00067 }
00068
00069 bool Path::contains(const FloatPoint& point, WindRule rule) const
00070 {
00071 Qt::FillRule savedRule = m_path->fillRule();
00072 m_path->setFillRule(rule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill);
00073
00074 bool contains = m_path->contains(point);
00075
00076 m_path->setFillRule(savedRule);
00077 return contains;
00078 }
00079
00080 void Path::translate(const FloatSize& size)
00081 {
00082 QMatrix matrix;
00083 matrix.translate(size.width(), size.height());
00084 *m_path = (*m_path) * matrix;
00085 }
00086
00087 FloatRect Path::boundingRect() const
00088 {
00089 return m_path->boundingRect();
00090 }
00091
00092 void Path::moveTo(const FloatPoint& point)
00093 {
00094 m_path->moveTo(point);
00095 }
00096
00097 void Path::addLineTo(const FloatPoint& p)
00098 {
00099 m_path->lineTo(p);
00100 }
00101
00102 void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p)
00103 {
00104 m_path->quadTo(cp, p);
00105 }
00106
00107 void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
00108 {
00109 m_path->cubicTo(cp1, cp2, p);
00110 }
00111
00112 void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
00113 {
00114
00115 qWarning("arcTo is busted");
00116 m_path->arcTo(p1.x(), p1.y(), p2.x(), p2.y(), radius, 90);
00117 }
00118
00119 void Path::closeSubpath()
00120 {
00121 m_path->closeSubpath();
00122 }
00123
00124 #define DEGREES(t) ((t) * 180.0 / M_PI)
00125 void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool anticlockwise)
00126 {
00127 qreal xc = p.x();
00128 qreal yc = p.y();
00129 qreal radius = r;
00130
00131
00132
00133
00134
00135
00136 sar = -sar;
00137 ear = -ear;
00138 anticlockwise = !anticlockwise;
00139
00140
00141 float sa = DEGREES(sar);
00142 float ea = DEGREES(ear);
00143
00144 double span = 0;
00145
00146 double xs = xc - radius;
00147 double ys = yc - radius;
00148 double width = radius*2;
00149 double height = radius*2;
00150
00151 if (!anticlockwise && (ea < sa))
00152 span += 360;
00153 else if (anticlockwise && (sa < ea))
00154 span -= 360;
00155
00156
00157
00158 if (!(qFuzzyCompare(span + (ea - sa), 0.0) &&
00159 qFuzzyCompare(qAbs(span), 360.0))) {
00160 span += ea - sa;
00161 }
00162
00163 m_path->moveTo(QPointF(xc + radius * cos(sar),
00164 yc - radius * sin(sar)));
00165
00166 m_path->arcTo(xs, ys, width, height, sa, span);
00167 }
00168
00169 void Path::addRect(const FloatRect& r)
00170 {
00171 m_path->addRect(r.x(), r.y(), r.width(), r.height());
00172 }
00173
00174 void Path::addEllipse(const FloatRect& r)
00175 {
00176 m_path->addEllipse(r.x(), r.y(), r.width(), r.height());
00177 }
00178
00179 void Path::clear()
00180 {
00181 *m_path = QPainterPath();
00182 }
00183
00184 bool Path::isEmpty() const
00185 {
00186 return m_path->isEmpty();
00187 }
00188
00189 String Path::debugString() const
00190 {
00191 QString ret;
00192 for (int i = 0; i < m_path->elementCount(); ++i) {
00193 const QPainterPath::Element &cur = m_path->elementAt(i);
00194
00195 switch (cur.type) {
00196 case QPainterPath::MoveToElement:
00197 ret += QString("M %1 %2").arg(cur.x).arg(cur.y);
00198 break;
00199 case QPainterPath::LineToElement:
00200 ret += QString("L %1 %2").arg(cur.x).arg(cur.y);
00201 break;
00202 case QPainterPath::CurveToElement:
00203 {
00204 const QPainterPath::Element &c1 = m_path->elementAt(i + 1);
00205 const QPainterPath::Element &c2 = m_path->elementAt(i + 2);
00206
00207 Q_ASSERT(c1.type == QPainterPath::CurveToDataElement);
00208 Q_ASSERT(c2.type == QPainterPath::CurveToDataElement);
00209
00210 ret += QString("C %1 %2 %3 %4 %5 %6").arg(cur.x).arg(cur.y).arg(c1.x).arg(c1.y).arg(c2.x).arg(c2.y);
00211
00212 i += 2;
00213 break;
00214 }
00215 case QPainterPath::CurveToDataElement:
00216 Q_ASSERT(false);
00217 break;
00218 }
00219 }
00220
00221 return ret;
00222 }
00223
00224 void Path::apply(void* info, PathApplierFunction function) const
00225 {
00226 PathElement pelement;
00227 FloatPoint points[3];
00228 pelement.points = points;
00229 for (int i = 0; i < m_path->elementCount(); ++i) {
00230 const QPainterPath::Element& cur = m_path->elementAt(i);
00231
00232 switch (cur.type) {
00233 case QPainterPath::MoveToElement:
00234 pelement.type = PathElementMoveToPoint;
00235 pelement.points[0] = QPointF(cur);
00236 function(info, &pelement);
00237 break;
00238 case QPainterPath::LineToElement:
00239 pelement.type = PathElementAddLineToPoint;
00240 pelement.points[0] = QPointF(cur);
00241 function(info, &pelement);
00242 break;
00243 case QPainterPath::CurveToElement:
00244 {
00245 const QPainterPath::Element& c1 = m_path->elementAt(i + 1);
00246 const QPainterPath::Element& c2 = m_path->elementAt(i + 2);
00247
00248 Q_ASSERT(c1.type == QPainterPath::CurveToDataElement);
00249 Q_ASSERT(c2.type == QPainterPath::CurveToDataElement);
00250
00251 pelement.type = PathElementAddCurveToPoint;
00252 pelement.points[0] = QPointF(cur);
00253 pelement.points[1] = QPointF(c1);
00254 pelement.points[2] = QPointF(c2);
00255 function(info, &pelement);
00256
00257 i += 2;
00258 break;
00259 }
00260 case QPainterPath::CurveToDataElement:
00261 Q_ASSERT(false);
00262 }
00263 }
00264 }
00265
00266 void Path::transform(const AffineTransform& transform)
00267 {
00268 if (m_path) {
00269 QMatrix mat = transform;
00270 QPainterPath temp = mat.map(*m_path);
00271 delete m_path;
00272 m_path = new QPainterPath(temp);
00273 }
00274 }
00275
00276 }
00277
00278