[Kst] [Bug 121068] Arrow view objects not always clipped correctly

Andrew Walker arwalker at sumusltd.com
Sun May 20 23:43:40 CEST 2007


------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.
         
http://bugs.kde.org/show_bug.cgi?id=121068         
arwalker sumusltd com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |FIXED



------- Additional Comments From arwalker sumusltd com  2007-05-20 23:43 -------
SVN commit 666781 by arwalker:

BUG:121068 Correctly handle clipping and selection of arrow view objects.

 M  +62 -38    kstviewarrow.cpp  
 M  +1 -0      kstviewarrow.h  
 M  +5 -5      kstviewellipse.cpp  
 M  +42 -32    kstviewline.cpp  
 M  +1 -0      kstviewline.h  


--- branches/work/kst/1.5/kst/src/libkstapp/kstviewarrow.cpp #666780:666781
 @ -29,6 +29,8  @
 #include <qpainter.h>
 #include <qvariant.h>
 
+#define SIZE_ARROW (2.0 * sqrt(3.0))
+
 KstViewArrow::KstViewArrow()
 : KstViewLine("Arrow") {
   _editTitle = i18n("Edit Arrow");
 @ -54,9 +56,9  @
         setProperty(el.tagName().latin1(), QVariant(el.text()));  
       }  
     }
-    n = n.nextSibling();      
+    n = n.nextSibling();
   }
-  
+
   // always has this value
   _type = "Arrow";
   _editTitle = i18n("Edit Arrow");
 @ -70,7 +72,7  @
   _hasToArrow = arrow._hasToArrow;
   _fromArrowScaling = arrow._fromArrowScaling;
   _toArrowScaling = arrow._toArrowScaling;
-  
+
   // these always have these values
   _type = "Arrow";
   _standardActions |= Delete | Edit;
 @ -92,50 +94,48  @
 
 
 void KstViewArrow::paintArrow(KstPainter& p, const QPoint& to, const QPoint &from, int w, double scaling) {
-  double deltax = scaling * 2.0 * double(w);
+  double deltax = scaling * double(w);
   double theta = atan2(double(from.y() - to.y()), double(from.x() - to.x())) - M_PI / 2.0;
   double sina = sin(theta);
   double cosa = cos(theta);
-  double yin = sqrt(3.0) * deltax;
+  double yin = SIZE_ARROW * deltax;
   double x1, y1, x2, y2;
   QWMatrix m(cosa, sina, -sina, cosa, 0.0, 0.0);
-  
+
   m.map( deltax, yin, &x1, &y1);
   m.map(-deltax, yin, &x2, &y2);
-  
+
   QPointArray pts(3);
   pts[0] = to;
   pts[1] = to + QPoint(d2i(x1), d2i(y1));
   pts[2] = to + QPoint(d2i(x2), d2i(y2));
-  
+
   p.drawPolygon(pts);
 }
 
 
 QRegion KstViewArrow::clipRegion() {
   if (_clipMask.isNull()) {
+    double scaling = kMax(_fromArrowScaling, _toArrowScaling);
+    int w = int(ceil(SIZE_ARROW * scaling * double(width())));
+    QRect rect(0, 0, _geom.bottomRight().x() + w + 1, _geom.bottomRight().y() + w + 1);
     _myClipMask = QRegion();
-    QBitmap bm1(_geom.bottomRight().x(), _geom.bottomRight().y(), true);
-    if (!bm1.isNull()) {
+    QBitmap bm(rect.size(), true);
+    if (!bm.isNull()) {
       KstPainter p;
+
       p.setMakingMask(true);
-      p.begin(&bm1);
+      p.begin(&bm);
       p.setViewXForm(true);
       KstViewLine::paintSelf(p, QRegion());
       p.flush();
-      p.end();
-      _clipMask = QRegion(bm1);
-    }
-    QBitmap bm2(_geom.bottomRight().x(), _geom.bottomRight().y(), true);
-    if (!bm2.isNull()) {
-      KstPainter p;
-      p.setMakingMask(true);
-      p.begin(&bm2);
-      p.setViewXForm(true);
+      _clipMask = QRegion(bm);
+
+      p.eraseRect(rect);
       paintSelf(p, QRegion());
       p.flush();
+      _myClipMask = QRegion(bm);
       p.end();
-      _myClipMask = QRegion(bm2);
     }
   }
 
 @ -154,23 +154,23  @
       p.setClipRegion(bounds & clip);
     }
   } else {
-      KstViewLine::paintSelf(p, bounds);
+    KstViewLine::paintSelf(p, bounds);
   }
-  
+
   if (hasArrow()) {
     QPoint to = KstViewLine::to();
-    QPoint from = KstViewLine::from();    
+    QPoint from = KstViewLine::from();
     const int w = width() * p.lineWidthAdjustmentFactor();
     QPen pen(_foregroundColor, w);
-    
+
     pen.setCapStyle(capStyle());
     p.setPen(pen);
     p.setBrush(_foregroundColor);
-    
-    if (_hasToArrow) {      
+
+    if (_hasToArrow) {
       paintArrow(p, to, from, w, _toArrowScaling);
     }
-    if (_hasFromArrow) {      
+    if (_hasFromArrow) {
       paintArrow(p, from, to, w, _fromArrowScaling);
     }
   }
 @ -220,40 +220,40  @
 
 
 bool KstViewArrow::hasFromArrow() const {
-  return _hasFromArrow;  
+  return _hasFromArrow;
 }
 
 
 void KstViewArrow::setHasFromArrow(bool yes) {
   if (_hasFromArrow != yes) {
-    _hasFromArrow = yes;  
+    _hasFromArrow = yes;
     setDirty();
   }
 }
 
 
 bool KstViewArrow::hasToArrow() const {
-  return _hasToArrow;  
+  return _hasToArrow;
 }
 
 
 void KstViewArrow::setHasToArrow(bool yes) {
   if (_hasToArrow != yes) {
-    _hasToArrow = yes;  
+    _hasToArrow = yes;
     setDirty();
   }
 }
 
 
 double KstViewArrow::fromArrowScaling() const {
-  return _fromArrowScaling;  
+  return _fromArrowScaling;
 }
 
 
 void KstViewArrow::setFromArrowScaling(double scaling) {
   if (scaling < 1.0) {
-    scaling = 1.0;  
-  }  
+    scaling = 1.0;
+  }
   if (_fromArrowScaling != scaling) {
     _fromArrowScaling = scaling;
     setDirty();
 @ -262,14 +262,14  @
 
 
 double KstViewArrow::toArrowScaling() const {
-  return _toArrowScaling;  
+  return _toArrowScaling;
 }
 
 
 void KstViewArrow::setToArrowScaling(double scaling) {
   if (scaling < 1.0) {
-    scaling = 1.0;  
-  }  
+    scaling = 1.0;
+  }
   if (_toArrowScaling != scaling) {
     _toArrowScaling = scaling;
     setDirty();
 @ -277,6 +277,30  @
 }
 
 
+QRect KstViewArrow::surroundingGeometry() const {
+  QRect geom(geometry());
+
+  if (_hasFromArrow || _hasToArrow) {
+    double scaling;
+    if (_hasFromArrow && _hasToArrow) {
+      scaling = kMax(_fromArrowScaling, _toArrowScaling);
+    } else if (_hasFromArrow) {
+      scaling = _fromArrowScaling;
+    } else {
+      scaling = _toArrowScaling;
+    }
+    geom.setLeft(geom.left() - int( SIZE_ARROW * scaling * double(width()/2.0) ) - 1);
+    geom.setRight(geom.right() + int( SIZE_ARROW * scaling * double(width()/2.0) ) + 1);
+    geom.setTop(geom.top() - int( SIZE_ARROW * scaling * double(width()/2.0) ) - 1);
+    geom.setBottom(geom.bottom() + int( SIZE_ARROW * scaling * double(width()/2.0) ) + 1);
+  } else {
+    geom = KstViewLine::surroundingGeometry();
+  }
+
+  return geom;
+}
+
+
 namespace {
 KstViewObject *create_KstViewArrow() {
   return new KstViewArrow;
--- branches/work/kst/1.5/kst/src/libkstapp/kstviewarrow.h #666780:666781
 @ -55,6 +55,7  @
     double toArrowScaling() const;
     void setToArrowScaling(double scaling);
     QRegion clipRegion();
+    virtual QRect surroundingGeometry() const;
 
   public:
     void save(QTextStream& ts, const QString& indent = QString::null);
--- branches/work/kst/1.5/kst/src/libkstapp/kstviewellipse.cpp #666780:666781
 @ -46,9 +46,9  @
         setProperty(el.tagName().latin1(), QVariant(el.text()));  
       }  
     }
-    n = n.nextSibling();      
+    n = n.nextSibling();
   }
-  
+
   // always have these values
   _type = "Ellipse";
   _editTitle = i18n("Edit Ellipse");
 @ -63,7 +63,7  @
   _transparentFill = ellipse._transparentFill;
   _borderWidth = ellipse._borderWidth;
   _borderColor = ellipse._borderColor;
-  
+
   // these always have these values
   _type = "Ellipse";
   _standardActions |= Delete | Edit;
 @ -79,7 +79,7  @
 
   KstViewEllipse* viewEllipse = new KstViewEllipse(*this);
   parent.appendChild(viewEllipse, true);
-  
+
   return viewEllipse;
 }
 
 @ -201,7 +201,7  @
   p.drawEllipse(rect);  
 }
 
-    
+
 void KstViewEllipse::setTransparentFill(bool yes) {
   if (_transparentFill != yes) {
     _transparentFill = yes;
--- branches/work/kst/1.5/kst/src/libkstapp/kstviewline.cpp #666780:666781
 @ -22,6 +22,7  @
 
 #include <klocale.h>
 
+#include <qbitmap.h>
 #include <qmetaobject.h>
 #include <qpainter.h>
 #include <qvariant.h>
 @ -59,7 +60,7  @
     }
     n = n.nextSibling();
   }
-  
+
   switch (orientationInt) {
     case 1:
       _orientation = UpRight;
 @ -90,7 +91,7  @
   _penStyle = line._penStyle;
   _orientation = line._orientation;
   _width = line._width;
-  
+
   // these always have these values
   _type = "Line";
   _standardActions |= Delete | Edit;
 @ -106,7 +107,7  @
 
   KstViewLine* viewLine = new KstViewLine(*this);
   parent.appendChild(viewLine, true);
-  
+
   return viewLine;
 }
 
 @ -116,7 +117,6  @
   if (p.type() != KstPainter::P_PRINT && p.type() != KstPainter::P_EXPORT) {
     if (p.makingMask()) {
       p.setRasterOp(Qt::SetROP);
-      KstViewObject::paintSelf(p, geometry());
     } else {
       const QRegion clip(clipRegion());
       KstViewObject::paintSelf(p, bounds - clip);
 @ -132,29 +132,15  @
   p.setPen(pen);
 
   const QRect geom(geometry());
-  int u = 0, v = 0;
-  
-  // Adjust for large widths.  We don't want the line clipped because it goes
-  // out of the bounding box.
-  if (w > 1 && geom.height() > 0) {
-    double theta = atan(geom.width()/geom.height());
-    if (theta >= 0 && theta <= M_PI/4) {
-      u = int(fabs((w / 2.0) * (sin(theta) + cos(theta))));
-      v = int(fabs((w / 2.0) * (1.5*sin(theta) + 0.5*cos(theta))));
-    } else {
-      u = int(fabs((w / 2.0) * (1.5*sin(theta) + 0.5*cos(theta))));
-      v = int(fabs((w / 2.0) * (sin(theta) + cos(theta))));
-    }
-  }
 
   switch (_orientation) {
     case UpLeft:
     case DownRight:
-      p.drawLine(geom.bottomRight() + QPoint(-u, -v), geom.topLeft() + QPoint(u, v));
+      p.drawLine(geom.bottomRight(), geom.topLeft());
       break;
     case UpRight:
     case DownLeft:
-      p.drawLine(geom.bottomLeft() + QPoint(u, -v), geom.topRight() + QPoint(-u, v));
+      p.drawLine(geom.bottomLeft(), geom.topRight());
       break;
   }
   p.restore();
 @ -260,6 +246,31  @
 }
 
 
+QRegion KstViewLine::clipRegion() {
+  if (_clipMask.isNull()) {
+    int w = width();
+    QRect rect(0, 0, _geom.bottomRight().x() + w + 1, _geom.bottomRight().y() + w + 1);
+    QBitmap bm(rect.size(), true);
+
+    if (!bm.isNull()) {
+      KstPainter p;
+      p.setMakingMask(true);
+      p.begin(&bm);
+      p.setViewXForm(true);
+      p.eraseRect(rect);
+      paintSelf(p, QRegion());
+      p.flush();
+      p.end();
+      _clipMask = QRegion(bm);
+    } else {
+      _clipMask = QRegion(); // only invalidate our own variable
+    }
+  }
+
+  return _clipMask; 
+}
+
+
 void KstViewLine::move(const QPoint& pos) {
   KstViewObject::move(pos);
   if (_from.x() < _to.x()) {
 @ -287,21 +298,21  @
     if (_from.y() < _to.y()) {
       _orientation = DownRight;  
       KstViewObject::move(_from);
-      KstViewObject::resize(QSize(kMax(_width, _to.x() - _from.x() + 1), kMax(_width, _to.y() - _from.y() + 1)));
+      KstViewObject::resize(QSize(_to.x() - _from.x() + 1, _to.y() - _from.y() + 1));
     } else {
       _orientation = UpRight;  
       KstViewObject::move(QPoint(_from.x(), _to.y()));
-      KstViewObject::resize(QSize(kMax(_width, _to.x() - _from.x() + 1), kMax(_width, _from.y() - _to.y() + 1)));
+      KstViewObject::resize(QSize(_to.x() - _from.x() + 1, _from.y() - _to.y() + 1));
     }
   } else {
     if (_from.y() < _to.y()) {
       _orientation = DownLeft;  
       KstViewObject::move(QPoint(_to.x(), _from.y()));
-      KstViewObject::resize(QSize(kMax(_width, _from.x() - _to.x() + 1), kMax(_width, _to.y() - _from.y() + 1)));
+      KstViewObject::resize(QSize(_from.x() - _to.x() + 1, _to.y() - _from.y() + 1));
     } else {
       _orientation = UpLeft;  
       KstViewObject::move(_to);
-      KstViewObject::resize(QSize(kMax(_width, _from.x() - _to.x() + 1), kMax(_width, _from.y() - _to.y() + 1)));
+      KstViewObject::resize(QSize(_from.x() - _to.x() + 1, _from.y() - _to.y() + 1));
     }
   }
 }
 @ -310,7 +321,7  @
 void KstViewLine::drawFocusRect(KstPainter& p) {
   // draw the hotpoints
   QPoint point1, point2;
-  
+
   const int dx = KST_RESIZE_BORDER_W/2;
 
   const QRect geom(geometry());
 @ -348,9 +359,9  @
 
 signed int KstViewLine::directionFor(const QPoint& pos) {
   if (!isSelected()) {
-    return NONE;  
+    return NONE;
   }
-  
+
   const QRect geom(geometry());
   switch (_orientation) {
     case UpLeft:
 @ -393,7 +404,7  @
   if (!map.empty()) {
     return map;  
   }
-  
+
   if (propertyName == "width") {
     map.insert(QString("_kst_widgetType"), QString("QSpinBox"));
     map.insert(QString("_kst_label"), i18n("Line width"));  
 @ -475,15 +486,14  @
 
 QRect KstViewLine::surroundingGeometry() const {
   QRect geom(geometry());
-  if (from().x() == to().x()) {
-    //vertical line
+
+  if (width() > 1) {
     geom.setLeft(geom.left() - width()/2 - 1);
     geom.setRight(geom.right() + width()/2 + 1);
-  } else if (from().y() == to().y()) {
-    //horizontal line
     geom.setTop(geom.top() - width()/2 - 1);
     geom.setBottom(geom.bottom() + width()/2 + 1);
   }
+
   return geom;
 }
 
--- branches/work/kst/1.5/kst/src/libkstapp/kstviewline.h #666780:666781
 @ -54,6 +54,7  @
     void setForegroundColor(const QColor& color);
     QColor foregroundColor() const;
 
+    QRegion clipRegion();
     void move(const QPoint& pos);
 
     virtual void setCapStyle(Qt::PenCapStyle style);


More information about the Kst mailing list