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