Draw last (half-) segment of stroke to make drawing feel smoother

Also, clarified the difference between received and drawn points
in UBGraphicsStroke
preferencesAboutTextFull
Craig Watson 9 years ago
parent b55ab7c92c
commit 43e0e414c9
  1. 25
      src/domain/UBGraphicsScene.cpp
  2. 1
      src/domain/UBGraphicsScene.h
  3. 31
      src/domain/UBGraphicsStroke.cpp
  4. 8
      src/domain/UBGraphicsStroke.h

@ -335,6 +335,7 @@ UBGraphicsScene::UBGraphicsScene(UBDocumentProxy* parent, bool enableUndoRedoSta
, mZLayerController(new UBZLayerController(this)) , mZLayerController(new UBZLayerController(this))
, mpLastPolygon(NULL) , mpLastPolygon(NULL)
, mCurrentPolygon(0) , mCurrentPolygon(0)
, mTempPolygon(NULL)
, mSelectionFrame(0) , mSelectionFrame(0)
{ {
UBCoreGraphicsScene::setObjectName("BoardScene"); UBCoreGraphicsScene::setObjectName("BoardScene");
@ -561,6 +562,23 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres
if (newPoints.length() > 1) { if (newPoints.length() > 1) {
drawCurve(newPoints, mPreviousWidth, width); drawCurve(newPoints, mPreviousWidth, width);
} }
if (interpolator == UBInterpolator::Bezier) {
// Bezier curves aren't drawn all the way to the scenePos (they stop halfway between the previous and
// current scenePos), so we add a line from the last drawn position in the stroke and the
// scenePos, to make the drawing feel more responsive. This line is then deleted if a new segment is
// added to the stroke. (Or it is added to the stroke when we stop drawing)
if (mTempPolygon) {
removeItem(mTempPolygon);
mTempPolygon = NULL;
}
QPointF lastDrawnPoint = newPoints.last();
mTempPolygon = lineToPolygonItem(QLineF(lastDrawnPoint, scenePos), mPreviousWidth, width);
addItem(mTempPolygon);
}
} }
} }
else if (currentTool == UBStylusTool::Eraser) else if (currentTool == UBStylusTool::Eraser)
@ -629,6 +647,13 @@ bool UBGraphicsScene::inputDeviceRelease()
mDrawWithCompass = false; mDrawWithCompass = false;
} }
else if (mCurrentStroke){ else if (mCurrentStroke){
if (mTempPolygon) {
UBGraphicsPolygonItem * poly = dynamic_cast<UBGraphicsPolygonItem*>(mTempPolygon->deepCopy());
removeItem(mTempPolygon);
mTempPolygon = NULL;
addPolygonItemToCurrentStroke(poly);
}
UBGraphicsStrokesGroup* pStrokes = new UBGraphicsStrokesGroup(); UBGraphicsStrokesGroup* pStrokes = new UBGraphicsStrokesGroup();
// Remove the strokes that were just drawn here and replace them by a stroke item // Remove the strokes that were just drawn here and replace them by a stroke item

@ -442,6 +442,7 @@ public slots:
UBZLayerController *mZLayerController; UBZLayerController *mZLayerController;
UBGraphicsPolygonItem* mpLastPolygon; UBGraphicsPolygonItem* mpLastPolygon;
UBGraphicsPolygonItem* mTempPolygon;
bool mDrawWithCompass; bool mDrawWithCompass;
UBGraphicsPolygonItem *mCurrentPolygon; UBGraphicsPolygonItem *mCurrentPolygon;

@ -70,18 +70,18 @@ QList<UBGraphicsPolygonItem*> UBGraphicsStroke::polygons() const
*/ */
QList<QPointF> UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator::InterpolationMethod interpolationMethod) QList<QPointF> UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator::InterpolationMethod interpolationMethod)
{ {
int n = mDrawnPoints.size(); int n = mReceivedPoints.size();
if (n == 0) { if (n == 0) {
mReceivedPoints << point;
mDrawnPoints << point; mDrawnPoints << point;
mAllPoints << point;
return QList<QPointF>(); return QList<QPointF>();
} }
if (interpolationMethod == UBInterpolator::NoInterpolation) { if (interpolationMethod == UBInterpolator::NoInterpolation) {
QPointF lastPoint = mDrawnPoints.last(); QPointF lastPoint = mReceivedPoints.last();
mReceivedPoints << point;
mDrawnPoints << point; mDrawnPoints << point;
mAllPoints << point;
return QList<QPointF>() << lastPoint << point; return QList<QPointF>() << lastPoint << point;
} }
@ -91,23 +91,24 @@ QList<QPointF> UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator::
// Don't draw segments smaller than a certain length. This can help with performance // Don't draw segments smaller than a certain length. This can help with performance
// (less polygons in a stroke) but mostly with keeping the curve smooth. // (less polygons in a stroke) but mostly with keeping the curve smooth.
qreal MIN_DISTANCE = 3*mAntiScaleRatio; qreal MIN_DISTANCE = 5*mAntiScaleRatio;
qreal distance = QLineF(mDrawnPoints.last(), point).length(); qreal distance = QLineF(mReceivedPoints.last(), point).length();
if (distance < MIN_DISTANCE) { if (distance < MIN_DISTANCE) {
return QList<QPointF>(); return QList<QPointF>() << mDrawnPoints.last();
} }
// The first segment is just a straight line to the first midway point // The first segment is just a straight line to the first midway point
if (n == 1) { if (n == 1) {
QPointF lastPoint = mDrawnPoints[0]; QPointF lastPoint = mReceivedPoints[0];
mDrawnPoints << point; mReceivedPoints << point;
mDrawnPoints << QPointF((lastPoint + point)/2.0);
return QList<QPointF>() << lastPoint << ((lastPoint + point)/2.0); return QList<QPointF>() << lastPoint << ((lastPoint + point)/2.0);
} }
QPointF p0 = mDrawnPoints[mDrawnPoints.size() - 2]; QPointF p0 = mReceivedPoints[mReceivedPoints.size() - 2];
QPointF p1 = mDrawnPoints[mDrawnPoints.size() - 1]; QPointF p1 = mReceivedPoints[mReceivedPoints.size() - 1];
QPointF p2 = point; QPointF p2 = point;
UBQuadraticBezier bz; UBQuadraticBezier bz;
@ -119,11 +120,15 @@ QList<QPointF> UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator::
QList<QPointF> newPoints = bz.getPoints(10); QList<QPointF> newPoints = bz.getPoints(10);
// avoid adding duplicates
if (newPoints.first() == mDrawnPoints.last())
mDrawnPoints.removeLast();
foreach(QPointF p, newPoints) { foreach(QPointF p, newPoints) {
mAllPoints << p; mDrawnPoints << p;
} }
mDrawnPoints << point; mReceivedPoints << point;
return newPoints; return newPoints;
} }

@ -59,7 +59,7 @@ class UBGraphicsStroke
QList<QPointF> addPoint(const QPointF& point, UBInterpolator::InterpolationMethod interpolationMethod = UBInterpolator::NoInterpolation); QList<QPointF> addPoint(const QPointF& point, UBInterpolator::InterpolationMethod interpolationMethod = UBInterpolator::NoInterpolation);
const QList<QPointF>& points() { return mAllPoints; } const QList<QPointF>& points() { return mDrawnPoints; }
protected: protected:
void addPolygon(UBGraphicsPolygonItem* pol); void addPolygon(UBGraphicsPolygonItem* pol);
@ -68,11 +68,11 @@ class UBGraphicsStroke
QList<UBGraphicsPolygonItem*> mPolygons; QList<UBGraphicsPolygonItem*> mPolygons;
/// Points that were drawn by the user (actually received through input device) /// Points that were drawn by the user (i.e, actually received through input device)
QList<QPointF> mDrawnPoints; QList<QPointF> mReceivedPoints;
/// All the points (including interpolated) that are used to draw the stroke /// All the points (including interpolated) that are used to draw the stroke
QList<QPointF> mAllPoints; QList<QPointF> mDrawnPoints;
qreal mAntiScaleRatio; qreal mAntiScaleRatio;
}; };

Loading…
Cancel
Save