File indexing completed on 2024-05-19 13:32:56

0001 /***************************************************************************
0002  *   Copyright (C) 1999-2005 Trolltech AS                                  *
0003  *   Copyright (C) 2006 David Saxton <david@bluehaze.org>                  *
0004  *                                                                         *
0005  *   This file may be distributed and/or modified under the terms of the   *
0006  *   GNU General Public License version 2 as published by the Free         *
0007  *   Software Foundation                                                   *
0008  ***************************************************************************/
0009 
0010 #include "canvasitems.h"
0011 #include "canvas.h"
0012 #include "canvas_private.h"
0013 
0014 #include <QBrush>
0015 #include <QPainter>
0016 #include <QPainterPath>
0017 #include <QPen>
0018 #include <QPolygon>
0019 #include <QRect>
0020 
0021 #include <ktechlab_debug.h>
0022 
0023 static bool isCanvasDebugEnabled()
0024 {
0025     return false;
0026 }
0027 
0028 KtlQCanvasItem::KtlQCanvasItem(KtlQCanvas *canvas)
0029     : val(false)
0030     , myx(0)
0031     , myy(0)
0032     , myz(0)
0033     , cnv(canvas)
0034     , ext(nullptr)
0035     , m_bNeedRedraw(true)
0036     , vis(false)
0037     , sel(false)
0038 {
0039     if (isCanvasDebugEnabled()) {
0040         qCDebug(KTL_LOG) << " this=" << this;
0041     }
0042     if (cnv)
0043         cnv->addItem(this);
0044 }
0045 
0046 KtlQCanvasItem::~KtlQCanvasItem()
0047 {
0048     if (cnv)
0049         cnv->removeItem(this);
0050     delete ext;
0051 }
0052 
0053 KtlQCanvasItemExtra &KtlQCanvasItem::extra()
0054 {
0055     if (!ext)
0056         ext = new KtlQCanvasItemExtra;
0057     return *ext;
0058 }
0059 
0060 void KtlQCanvasItem::setZ(double a)
0061 {
0062     if (myz == a)
0063         return;
0064 
0065     // remove and then add the item so that z-ordered list in canvas is updated
0066 
0067     if (cnv)
0068         cnv->removeItem(this);
0069 
0070     myz = a;
0071     changeChunks();
0072 
0073     if (cnv)
0074         cnv->addItem(this);
0075 }
0076 
0077 void KtlQCanvasItem::moveBy(const double dx, const double dy)
0078 {
0079     if (dx || dy) {
0080         removeFromChunks();
0081         myx += dx;
0082         myy += dy;
0083         addToChunks();
0084     }
0085 }
0086 
0087 void KtlQCanvasItem::move(const double x, const double y)
0088 {
0089     moveBy(x - myx, y - myy);
0090 }
0091 
0092 void KtlQCanvasItem::setCanvas(KtlQCanvas *c)
0093 {
0094     bool v = isVisible();
0095     setVisible(false);
0096     if (cnv) {
0097         cnv->removeItem(this);
0098     }
0099 
0100     cnv = c;
0101 
0102     if (cnv) {
0103         cnv->addItem(this);
0104     }
0105 
0106     setVisible(v);
0107 }
0108 
0109 void KtlQCanvasItem::show()
0110 {
0111     setVisible(true);
0112 }
0113 
0114 void KtlQCanvasItem::hide()
0115 {
0116     setVisible(false);
0117 }
0118 
0119 void KtlQCanvasItem::setVisible(bool yes)
0120 {
0121     if (vis != yes) {
0122         if (yes) {
0123             vis = uint(yes);
0124             addToChunks();
0125         } else {
0126             removeFromChunks();
0127             vis = uint(yes);
0128         }
0129     }
0130 }
0131 
0132 void KtlQCanvasItem::setSelected(const bool yes)
0133 {
0134     if (bool(sel) != yes) {
0135         sel = uint(yes);
0136         changeChunks();
0137     }
0138 }
0139 
0140 static bool collision_double_dispatch(const KtlQCanvasPolygonalItem *p1, const KtlQCanvasRectangle *r1, const KtlQCanvasEllipse *e1, const KtlQCanvasPolygonalItem *p2, const KtlQCanvasRectangle *r2, const KtlQCanvasEllipse *e2)
0141 {
0142     const KtlQCanvasItem *i1 = nullptr;
0143     if (p1) {
0144         i1 = p1;
0145     } else {
0146         if (r1) {
0147             i1 = r1;
0148         } else {
0149             i1 = e1;
0150         }
0151     }
0152     const KtlQCanvasItem *i2 = nullptr;
0153     if (i2) {
0154         i2 = p2;
0155     } else {
0156         if (r2) {
0157             i2 = r2;
0158         } else {
0159             i2 = e2;
0160         }
0161     }
0162     //  const KtlQCanvasItem* i1 = p1 ?
0163     //          (const KtlQCanvasItem*)p1 : r1 ?
0164     //          (const KtlQCanvasItem*)r1 : (const KtlQCanvasItem*)e1;
0165     //  const KtlQCanvasItem* i2 = p2 ?
0166     //          (const KtlQCanvasItem*)p2 : r2 ?
0167     //          (const KtlQCanvasItem*)r2 : (const KtlQCanvasItem*)e2;
0168 
0169     if (r1 && r2) {
0170         // b
0171         QRect rc1 = i1->boundingRect();
0172         QRect rc2 = i2->boundingRect();
0173         return rc1.intersects(rc2);
0174     } else if (e1 && e2 && e1->angleLength() >= 360 * 16 && e2->angleLength() >= 360 * 16 && e1->width() == e1->height() && e2->width() == e2->height()) {
0175         // c
0176         double xd = (e1->x()) - (e2->x());
0177         double yd = (e1->y()) - (e2->y());
0178         double rd = (e1->width() + e2->width()) / 2;
0179         return xd * xd + yd * yd <= rd * rd;
0180     } else if (p1 && p2) {
0181         // d
0182         QPolygon pa1 = p1->areaPoints();
0183         QPolygon pa2 = p2 ? p2->areaPoints() : QPolygon(i2->boundingRect());
0184         bool col = !(QRegion(pa1) & QRegion(pa2, /* true */ Qt::WindingFill)).isEmpty();
0185 
0186         return col;
0187     } else {
0188         return collision_double_dispatch(p2, r2, e2, p1, r1, e1);
0189     }
0190 }
0191 
0192 bool KtlQCanvasPolygonalItem::collidesWith(const KtlQCanvasItem *i) const
0193 {
0194     return i->collidesWith(this, nullptr, nullptr);
0195 }
0196 
0197 bool KtlQCanvasPolygonalItem::collidesWith(const KtlQCanvasPolygonalItem *p, const KtlQCanvasRectangle *r, const KtlQCanvasEllipse *e) const
0198 {
0199     return collision_double_dispatch(p, r, e, this, nullptr, nullptr);
0200 }
0201 
0202 bool KtlQCanvasRectangle::collidesWith(const KtlQCanvasItem *i) const
0203 {
0204     return i->collidesWith(this, this, nullptr);
0205 }
0206 
0207 bool KtlQCanvasRectangle::collidesWith(const KtlQCanvasPolygonalItem *p, const KtlQCanvasRectangle *r, const KtlQCanvasEllipse *e) const
0208 {
0209     return collision_double_dispatch(p, r, e, this, this, nullptr);
0210 }
0211 
0212 bool KtlQCanvasEllipse::collidesWith(const KtlQCanvasItem *i) const
0213 {
0214     return i->collidesWith(this, nullptr, this);
0215 }
0216 
0217 bool KtlQCanvasEllipse::collidesWith(const KtlQCanvasPolygonalItem *p, const KtlQCanvasRectangle *r, const KtlQCanvasEllipse *e) const
0218 {
0219     return collision_double_dispatch(p, r, e, this, nullptr, this);
0220 }
0221 
0222 KtlQCanvasItemList KtlQCanvasItem::collisions(const bool exact) const
0223 {
0224     return canvas()->collisions(chunks(), this, exact);
0225 }
0226 
0227 void KtlQCanvasItem::addToChunks()
0228 {
0229     if (isVisible() && canvas()) {
0230         QPolygon pa = chunks();
0231         for (int i = 0; i < int(pa.count()); i++)
0232             canvas()->addItemToChunk(this, pa[i].x(), pa[i].y());
0233         val = true;
0234     }
0235 }
0236 
0237 void KtlQCanvasItem::removeFromChunks()
0238 {
0239     if (isVisible() && canvas()) {
0240         QPolygon pa = chunks();
0241         for (int i = 0; i < int(pa.count()); i++)
0242             canvas()->removeItemFromChunk(this, pa[i].x(), pa[i].y());
0243     }
0244 }
0245 
0246 void KtlQCanvasItem::changeChunks()
0247 {
0248     if (isVisible() && canvas()) {
0249         if (!val)
0250             addToChunks();
0251         QPolygon pa = chunks();
0252         for (int i = 0; i < int(pa.count()); i++)
0253             canvas()->setChangedChunk(pa[i].x(), pa[i].y());
0254     }
0255 }
0256 
0257 QPolygon KtlQCanvasItem::chunks() const
0258 {
0259     QPolygon r;
0260     int n = 0;
0261     QRect br = boundingRect();
0262     if (isVisible() && canvas()) {
0263         br &= canvas()->rect();
0264         if (br.isValid()) {
0265             r.resize((canvas()->toChunkScaling(br.width()) + 2) * (canvas()->toChunkScaling(br.height()) + 2));
0266             for (int j = canvas()->toChunkScaling(br.top()); j <= canvas()->toChunkScaling(br.bottom()); j++) {
0267                 for (int i = canvas()->toChunkScaling(br.left()); i <= canvas()->toChunkScaling(br.right()); i++) {
0268                     r[n++] = QPoint(i, j);
0269                 }
0270             }
0271         }
0272     }
0273     r.resize(n);
0274     return r;
0275 }
0276 
0277 /*
0278     Since most polygonal items don't have a pen, the default is
0279     NoPen and a black brush.
0280 */
0281 static const QPen &defaultPolygonPen()
0282 {
0283     static QPen *dp = nullptr;
0284     if (!dp)
0285         dp = new QPen;
0286     return *dp;
0287 }
0288 
0289 static const QBrush &defaultPolygonBrush()
0290 {
0291     static QBrush *db = nullptr;
0292     if (!db)
0293         db = new QBrush;
0294     return *db;
0295 }
0296 
0297 KtlQCanvasPolygonalItem::KtlQCanvasPolygonalItem(KtlQCanvas *canvas)
0298     : KtlQCanvasItem(canvas)
0299     , br(defaultPolygonBrush())
0300     , pn(defaultPolygonPen())
0301     , wind(false)
0302 {
0303     if (isCanvasDebugEnabled()) {
0304         qCDebug(KTL_LOG) << "created KtlQCanvasPolygonalItem at " << this;
0305     }
0306 }
0307 
0308 KtlQCanvasPolygonalItem::~KtlQCanvasPolygonalItem()
0309 {
0310     if (isCanvasDebugEnabled()) {
0311         qCDebug(KTL_LOG) << "destroying KtlQCanvasPolygonalItem at " << this;
0312     }
0313 }
0314 
0315 bool KtlQCanvasPolygonalItem::winding() const
0316 {
0317     return wind;
0318 }
0319 
0320 void KtlQCanvasPolygonalItem::setWinding(bool enable)
0321 {
0322     wind = enable;
0323 }
0324 
0325 void KtlQCanvasPolygonalItem::invalidate()
0326 {
0327     val = false;
0328     removeFromChunks();
0329 }
0330 
0331 QPolygon KtlQCanvasPolygonalItem::chunks() const
0332 {
0333     QPolygon pa = areaPoints();
0334 
0335     if (!pa.size()) {
0336         pa.detach(); // Explicit sharing is stupid.
0337         return pa;
0338     }
0339 
0340     KtlQPolygonalProcessor processor(canvas(), pa);
0341 
0342     scanPolygon(pa, wind, processor);
0343 
0344     return processor.result;
0345 }
0346 
0347 QPolygon KtlQCanvasRectangle::chunks() const
0348 {
0349     // No need to do a polygon scan!
0350     return KtlQCanvasItem::chunks();
0351 }
0352 
0353 QRect KtlQCanvasPolygonalItem::boundingRect() const
0354 {
0355     return areaPoints().boundingRect();
0356 }
0357 
0358 void KtlQCanvasPolygonalItem::draw(QPainter &p)
0359 {
0360     p.setPen(pn);
0361     p.setBrush(br);
0362     drawShape(p);
0363 }
0364 
0365 void KtlQCanvasPolygonalItem::setPen(const QPen &p)
0366 {
0367     if (pn == p)
0368         return;
0369 
0370     pn.setColor(p.color());
0371 
0372     // if only the color was different, then don't need to re-add to chunks
0373     if (pn == p) {
0374         changeChunks();
0375     } else {
0376         // Have to re-add to chunks as e.g. pen width might have changed
0377         removeFromChunks();
0378         pn = p;
0379         addToChunks();
0380     }
0381 }
0382 
0383 void KtlQCanvasPolygonalItem::setBrush(const QBrush &b)
0384 {
0385     if (br != b) {
0386         br = b;
0387         changeChunks();
0388     }
0389 }
0390 
0391 KtlQCanvasPolygon::KtlQCanvasPolygon(KtlQCanvas *canvas)
0392     : KtlQCanvasPolygonalItem(canvas)
0393     , guardBef()
0394     , poly(new QPolygon)
0395     , guardAft()
0396 {
0397     if (isCanvasDebugEnabled()) {
0398         qCDebug(KTL_LOG) << " this=" << this;
0399     }
0400 }
0401 
0402 KtlQCanvasPolygon::~KtlQCanvasPolygon()
0403 {
0404     hide();
0405     delete poly;
0406 }
0407 
0408 void KtlQCanvasPolygon::drawShape(QPainter &p)
0409 {
0410     // ### why can't we draw outlines? We could use drawPolyline for it. Lars
0411     // ### see other message. Warwick
0412 
0413     p.setPen(Qt::NoPen); // since QRegion(QPolygon) excludes outline :-(  )-:
0414     p.drawPolygon(*poly);
0415 }
0416 
0417 void KtlQCanvasPolygon::setPoints(QPolygon pa)
0418 {
0419     removeFromChunks();
0420     *poly = pa;
0421     poly->detach(); // Explicit sharing is stupid.
0422     poly->translate(int(x()), int(y()));
0423     addToChunks();
0424 }
0425 
0426 void KtlQCanvasPolygon::moveBy(double dx, double dy)
0427 {
0428     // Note: does NOT call KtlQCanvasPolygonalItem::moveBy(), since that
0429     // only does half this work.
0430     //
0431     int idx = int(x() + dx) - int(x());
0432     int idy = int(y() + dy) - int(y());
0433     if (idx || idy) {
0434         removeFromChunks();
0435         poly->translate(idx, idy);
0436     }
0437     myx += dx;
0438     myy += dy;
0439     if (idx || idy) {
0440         addToChunks();
0441     }
0442 }
0443 
0444 QPolygon KtlQCanvasPolygon::points() const
0445 {
0446     QPolygon pa = areaPoints();
0447     pa.translate(int(-x()), int(-y()));
0448     return pa;
0449 }
0450 
0451 QPolygon KtlQCanvasPolygon::areaPoints() const
0452 {
0453     return QPolygon(*poly); // ->copy(); // 2018.06.02 - copy is only in QPolygon
0454 }
0455 
0456 // ### mark: Why don't we offer a constructor that lets the user set the
0457 // points -- that way for some uses just the constructor call would be
0458 // required?
0459 
0460 KtlQCanvasLine::KtlQCanvasLine(KtlQCanvas *canvas)
0461     : KtlQCanvasPolygonalItem(canvas)
0462 {
0463     if (isCanvasDebugEnabled()) {
0464         qCDebug(KTL_LOG) << " this=" << this;
0465     }
0466     x1 = y1 = x2 = y2 = 0;
0467 }
0468 
0469 KtlQCanvasLine::~KtlQCanvasLine()
0470 {
0471     hide();
0472 }
0473 
0474 void KtlQCanvasLine::setPen(const QPen &p)
0475 {
0476     KtlQCanvasPolygonalItem::setPen(p);
0477 }
0478 
0479 void KtlQCanvasLine::setPoints(int xa, int ya, int xb, int yb)
0480 {
0481     if (x1 != xa || x2 != xb || y1 != ya || y2 != yb) {
0482         removeFromChunks();
0483         x1 = xa;
0484         y1 = ya;
0485         x2 = xb;
0486         y2 = yb;
0487         addToChunks();
0488     }
0489 }
0490 
0491 void KtlQCanvasLine::drawShape(QPainter &p)
0492 {
0493     p.drawLine(int(x() + x1), int(y() + y1), int(x() + x2), int(y() + y2));
0494 }
0495 
0496 QPolygon KtlQCanvasLine::areaPoints() const
0497 {
0498     QPolygon p(4);
0499     int xi = int(x());
0500     int yi = int(y());
0501     int pw = pen().width();
0502     int dx = abs(x1 - x2);
0503     int dy = abs(y1 - y2);
0504     pw = pw * 4 / 3 + 2; // approx pw*sqrt(2)
0505     int px = x1 < x2 ? -pw : pw;
0506     int py = y1 < y2 ? -pw : pw;
0507     if (dx && dy && (dx > dy ? (dx * 2 / dy <= 2) : (dy * 2 / dx <= 2))) {
0508         // steep
0509         if (px == py) {
0510             p[0] = QPoint(x1 + xi, y1 + yi + py);
0511             p[1] = QPoint(x2 + xi - px, y2 + yi);
0512             p[2] = QPoint(x2 + xi, y2 + yi - py);
0513             p[3] = QPoint(x1 + xi + px, y1 + yi);
0514         } else {
0515             p[0] = QPoint(x1 + xi + px, y1 + yi);
0516             p[1] = QPoint(x2 + xi, y2 + yi - py);
0517             p[2] = QPoint(x2 + xi - px, y2 + yi);
0518             p[3] = QPoint(x1 + xi, y1 + yi + py);
0519         }
0520     } else if (dx > dy) {
0521         // horizontal
0522         p[0] = QPoint(x1 + xi + px, y1 + yi + py);
0523         p[1] = QPoint(x2 + xi - px, y2 + yi + py);
0524         p[2] = QPoint(x2 + xi - px, y2 + yi - py);
0525         p[3] = QPoint(x1 + xi + px, y1 + yi - py);
0526     } else {
0527         // vertical
0528         p[0] = QPoint(x1 + xi + px, y1 + yi + py);
0529         p[1] = QPoint(x2 + xi + px, y2 + yi - py);
0530         p[2] = QPoint(x2 + xi - px, y2 + yi - py);
0531         p[3] = QPoint(x1 + xi - px, y1 + yi + py);
0532     }
0533     return p;
0534 }
0535 
0536 void KtlQCanvasLine::moveBy(double dx, double dy)
0537 {
0538     KtlQCanvasPolygonalItem::moveBy(dx, dy);
0539 }
0540 
0541 KtlQCanvasRectangle::KtlQCanvasRectangle(KtlQCanvas *canvas)
0542     : KtlQCanvasPolygonalItem(canvas)
0543     , w(32)
0544     , h(32)
0545 {
0546     setObjectName("KtlQCanvasRectangle");
0547     if (isCanvasDebugEnabled()) {
0548         qCDebug(KTL_LOG) << " this=" << this;
0549     }
0550 }
0551 
0552 KtlQCanvasRectangle::KtlQCanvasRectangle(const QRect &r, KtlQCanvas *canvas)
0553     : KtlQCanvasPolygonalItem(canvas)
0554     , w(r.width())
0555     , h(r.height())
0556 {
0557     setObjectName("KtlQCanvasRectangle");
0558     move(r.x(), r.y());
0559     if (isCanvasDebugEnabled()) {
0560         qCDebug(KTL_LOG) << " this=" << this;
0561     }
0562 }
0563 
0564 KtlQCanvasRectangle::KtlQCanvasRectangle(int x, int y, int width, int height, KtlQCanvas *canvas)
0565     : KtlQCanvasPolygonalItem(canvas)
0566     , w(width)
0567     , h(height)
0568 {
0569     setObjectName("KtlQCanvasRectangle");
0570     move(x, y);
0571     if (isCanvasDebugEnabled()) {
0572         qCDebug(KTL_LOG) << " this=" << this;
0573     }
0574 }
0575 
0576 KtlQCanvasRectangle::~KtlQCanvasRectangle()
0577 {
0578     hide();
0579 }
0580 
0581 int KtlQCanvasRectangle::width() const
0582 {
0583     return w;
0584 }
0585 
0586 int KtlQCanvasRectangle::height() const
0587 {
0588     return h;
0589 }
0590 
0591 void KtlQCanvasRectangle::setSize(const int width, const int height)
0592 {
0593     if (w != width || h != height) {
0594         removeFromChunks();
0595         w = width;
0596         h = height;
0597         addToChunks();
0598     }
0599 }
0600 
0601 QPolygon KtlQCanvasRectangle::areaPoints() const
0602 {
0603     QPolygon pa(4);
0604     int pw = (pen().width() + 1) / 2;
0605     if (pw < 1)
0606         pw = 1;
0607     if (pen() == Qt::NoPen)
0608         pw = 0;
0609     pa[0] = QPoint(int(x()) - pw, int(y()) - pw);
0610     pa[1] = pa[0] + QPoint(w + pw * 2, 0);
0611     pa[2] = pa[1] + QPoint(0, h + pw * 2);
0612     pa[3] = pa[0] + QPoint(0, h + pw * 2);
0613     return pa;
0614 }
0615 
0616 void KtlQCanvasRectangle::drawShape(QPainter &p)
0617 {
0618     p.drawRect(int(x()), int(y()), w, h);
0619 }
0620 
0621 KtlQCanvasEllipse::KtlQCanvasEllipse(KtlQCanvas *canvas)
0622     : KtlQCanvasPolygonalItem(canvas)
0623     , w(32)
0624     , h(32)
0625     , a1(0)
0626     , a2(360 * 16)
0627 {
0628     if (isCanvasDebugEnabled()) {
0629         qCDebug(KTL_LOG) << " this=" << this;
0630     }
0631 }
0632 
0633 /*!
0634     Constructs a \a width by \a height pixel ellipse, centered at
0635     (0, 0) on \a canvas.
0636  */
0637 KtlQCanvasEllipse::KtlQCanvasEllipse(int width, int height, KtlQCanvas *canvas)
0638     : KtlQCanvasPolygonalItem(canvas)
0639     , w(width)
0640     , h(height)
0641     , a1(0)
0642     , a2(360 * 16)
0643 {
0644     if (isCanvasDebugEnabled()) {
0645         qCDebug(KTL_LOG) << " this=" << this;
0646     }
0647 }
0648 
0649 KtlQCanvasEllipse::KtlQCanvasEllipse(int width, int height, int startangle, int angle, KtlQCanvas *canvas)
0650     : KtlQCanvasPolygonalItem(canvas)
0651     , w(width)
0652     , h(height)
0653     , a1(startangle)
0654     , a2(angle)
0655 {
0656     if (isCanvasDebugEnabled()) {
0657         qCDebug(KTL_LOG) << " this=" << this;
0658     }
0659 }
0660 
0661 KtlQCanvasEllipse::~KtlQCanvasEllipse()
0662 {
0663     hide();
0664 }
0665 
0666 int KtlQCanvasEllipse::width() const
0667 {
0668     return w;
0669 }
0670 
0671 int KtlQCanvasEllipse::height() const
0672 {
0673     return h;
0674 }
0675 
0676 void KtlQCanvasEllipse::setSize(int width, int height)
0677 {
0678     if (w != width || h != height) {
0679         removeFromChunks();
0680         w = width;
0681         h = height;
0682         addToChunks();
0683     }
0684 }
0685 
0686 void KtlQCanvasEllipse::setAngles(int start, int length)
0687 {
0688     if (a1 != start || a2 != length) {
0689         removeFromChunks();
0690         a1 = start;
0691         a2 = length;
0692         addToChunks();
0693     }
0694 }
0695 
0696 QPolygon KtlQCanvasEllipse::areaPoints() const
0697 {
0698     // Q3PointArray r;     // 2018.08.14 - see below
0699     // // makeArc at 0,0, then translate so that fixed point math doesn't overflow
0700     // r.makeArc(int(x()-w/2.0+0.5)-1, int(y()-h/2.0+0.5)-1, w+3, h+3, a1, a2);
0701 
0702     QPainterPath path;
0703     path.arcTo(int(x() - w / 2.0 + 0.5) - 1, int(y() - h / 2.0 + 0.5) - 1, w + 3, h + 3, a1, a2 - a1);
0704     QPolygon r = path.toFillPolygon().toPolygon();
0705 
0706     r.resize(r.size() + 1);
0707     r.setPoint(r.size() - 1, int(x()), int(y()));
0708     return QPolygon(r);
0709 }
0710 
0711 void KtlQCanvasEllipse::drawShape(QPainter &p)
0712 {
0713     p.setPen(Qt::NoPen); // since QRegion(QPolygon) excludes outline :-(  )-:
0714     if (!a1 && a2 == 360 * 16) {
0715         p.drawEllipse(int(x() - w / 2.0 + 0.5), int(y() - h / 2.0 + 0.5), w, h);
0716     } else {
0717         p.drawPie(int(x() - w / 2.0 + 0.5), int(y() - h / 2.0 + 0.5), w, h, a1, a2);
0718     }
0719 }
0720 
0721 void KtlQCanvasPolygonalItem::scanPolygon(const QPolygon &pa, int winding, KtlQPolygonalProcessor &process) const
0722 {
0723     KtlQCanvasPolygonScanner scanner(process);
0724     scanner.scan(pa, winding);
0725 }
0726 
0727 #include "moc_canvasitems.cpp"