[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