Index: libs/image/brushengine/kis_paint_information.h =================================================================== --- libs/image/brushengine/kis_paint_information.h +++ libs/image/brushengine/kis_paint_information.h @@ -27,6 +27,8 @@ #include #include "kis_random_source.h" +#include + class QDomDocument; class QDomElement; @@ -274,7 +276,15 @@ private: struct Private; - Private* const d; + static constexpr size_t _dStorageSize = 144; + // static constexpr size_t _dStorageAlign = 16; + std::aligned_storage<_dStorageSize /* , _dStorageAlign*/ >::type _dStorage; + Private* d() { + return reinterpret_cast(&_dStorage); + } + Private const* d() const { + return reinterpret_cast(&_dStorage); + } }; KRITAIMAGE_EXPORT QDebug operator<<(QDebug debug, const KisPaintInformation& info); Index: libs/image/brushengine/kis_paint_information.cc =================================================================== --- libs/image/brushengine/kis_paint_information.cc +++ libs/image/brushengine/kis_paint_information.cc @@ -21,7 +21,6 @@ #include #include -#include #include "kis_paintop.h" #include "kis_algebra_2d.h" @@ -31,7 +30,6 @@ #include struct KisPaintInformation::Private { - EIGEN_MAKE_ALIGNED_OPERATOR_NEW Private(const QPointF & pos_, qreal pressure_, @@ -127,13 +125,34 @@ DistanceInformationRegistrar(KisPaintInformation *_p, KisDistanceInformation *distanceInfo) : p(_p) { - p->d->registerDistanceInfo(distanceInfo); + p->d()->registerDistanceInfo(distanceInfo); } KisPaintInformation::DistanceInformationRegistrar:: ~DistanceInformationRegistrar() { - p->d->unregisterDistanceInfo(); + p->d()->unregisterDistanceInfo(); +} + +// Templates for showing the actual values in error messages +template +void check_storage_size() { + static_assert(sizeof(T) == sizeOfT, "boo"); + static_assert(sizeof(T) <= storageSize, + "KisPaintInformation::_dStorageSize too small"); + static_assert(storageSize <= sizeof(T) * 1.2, + "KisPaintInformation::_dStorageSize too much unused space"); +} +template +void check_align_multiple() { + static_assert(alignof(T) == alignOfT, "boo"); + static_assert(alignof(T) % align == 0, "Not aligned properly"); +} +template +void check_align_equal() { + static_assert(alignof(T1) == alignOfT1, "boo"); + static_assert(alignof(T2) == alignOfT2, "boo"); + static_assert(alignof(T1) == alignof(T2), "Not same alignment"); } KisPaintInformation::KisPaintInformation(const QPointF & pos, @@ -144,7 +163,10 @@ qreal perspective, qreal time, qreal speed) - : d(new Private(pos, +{ + check_storage_size(); + check_align_multiple(); + new(&_dStorage) Private(pos, pressure, xTilt, yTilt, rotation, @@ -152,8 +174,7 @@ perspective, time, speed, - false)) -{ + false); } KisPaintInformation::KisPaintInformation(const QPointF & pos, @@ -161,7 +182,8 @@ qreal xTilt, qreal yTilt, qreal rotation) - : d(new Private(pos, +{ + new(&_dStorage) Private(pos, pressure, xTilt, yTilt, rotation, @@ -169,14 +191,13 @@ 1.0, 0.0, 0.0, - false)) -{ - + false); } KisPaintInformation::KisPaintInformation(const QPointF &pos, qreal pressure) - : d(new Private(pos, +{ + new(&_dStorage) Private(pos, pressure, 0.0, 0.0, 0.0, @@ -184,28 +205,27 @@ 1.0, 0.0, 0.0, - false)) -{ + false); } KisPaintInformation::KisPaintInformation(const KisPaintInformation& rhs) - : d(new Private(*rhs.d)) { + new(&_dStorage) Private(*rhs.d()); } void KisPaintInformation::operator=(const KisPaintInformation & rhs) { - *d = *rhs.d; + *d() = *rhs.d(); } KisPaintInformation::~KisPaintInformation() { - delete d; + d()->~Private(); } bool KisPaintInformation::isHoveringMode() const { - return d->isHoveringMode; + return d()->isHoveringMode; } @@ -226,43 +246,43 @@ rotation, tangentialPressure, perspective, 0, speed); - info.d->isHoveringMode = true; - info.d->canvasRotation = canvasrotation; - info.d->canvasMirroredH = canvasMirroredH; + info.d()->isHoveringMode = true; + info.d()->canvasRotation = canvasrotation; + info.d()->canvasMirroredH = canvasMirroredH; return info; } int KisPaintInformation::canvasRotation() const { - return d->canvasRotation; + return d()->canvasRotation; } void KisPaintInformation::setCanvasRotation(int rotation) { if (rotation < 0) { - d->canvasRotation= 360- abs(rotation % 360); + d()->canvasRotation= 360- abs(rotation % 360); } else { - d->canvasRotation= rotation % 360; + d()->canvasRotation= rotation % 360; } } bool KisPaintInformation::canvasMirroredH() const { - return d->canvasMirroredH; + return d()->canvasMirroredH; } void KisPaintInformation::setCanvasHorizontalMirrorState(bool mir) { - d->canvasMirroredH = mir; + d()->canvasMirroredH = mir; } void KisPaintInformation::toXML(QDomDocument&, QDomElement& e) const { // hovering mode infos are not supposed to be saved - KIS_ASSERT_RECOVER_NOOP(!d->isHoveringMode); + KIS_ASSERT_RECOVER_NOOP(!d()->isHoveringMode); e.setAttribute("pointX", QString::number(pos().x(), 'g', 15)); e.setAttribute("pointY", QString::number(pos().y(), 'g', 15)); @@ -272,8 +292,8 @@ e.setAttribute("rotation", QString::number(rotation(), 'g', 15)); e.setAttribute("tangentialPressure", QString::number(tangentialPressure(), 'g', 15)); e.setAttribute("perspective", QString::number(perspective(), 'g', 15)); - e.setAttribute("time", QString::number(d->time, 'g', 15)); - e.setAttribute("speed", QString::number(d->speed, 'g', 15)); + e.setAttribute("time", QString::number(d()->time, 'g', 15)); + e.setAttribute("speed", QString::number(d()->speed, 'g', 15)); } KisPaintInformation KisPaintInformation::fromXML(const QDomElement& e) @@ -295,42 +315,42 @@ const QPointF& KisPaintInformation::pos() const { - return d->pos; + return d()->pos; } void KisPaintInformation::setPos(const QPointF& p) { - d->pos = p; + d()->pos = p; } qreal KisPaintInformation::pressure() const { - return d->pressure; + return d()->pressure; } void KisPaintInformation::setPressure(qreal p) { - d->pressure = p; + d()->pressure = p; } qreal KisPaintInformation::xTilt() const { - return d->xTilt; + return d()->xTilt; } qreal KisPaintInformation::yTilt() const { - return d->yTilt; + return d()->yTilt; } void KisPaintInformation::overrideDrawingAngle(qreal angle) { - d->drawingAngleOverride.reset(new qreal(angle)); + d()->drawingAngleOverride.reset(new qreal(angle)); } qreal KisPaintInformation::drawingAngleSafe(const KisDistanceInformation &distance) const { - if (d->drawingAngleOverride) return *d->drawingAngleOverride; + if (d()->drawingAngleOverride) return *d()->drawingAngleOverride; if (!distance.hasLastDabInformation()) { warnKrita << "KisPaintInformation::drawingAngleSafe()" << "Cannot access Distance Info last dab data"; @@ -348,35 +368,35 @@ qreal KisPaintInformation::drawingAngle() const { - if (d->drawingAngleOverride) return *d->drawingAngleOverride; + if (d()->drawingAngleOverride) return *d()->drawingAngleOverride; - if (!d->currentDistanceInfo || !d->currentDistanceInfo->hasLastDabInformation()) { + if (!d()->currentDistanceInfo || !d()->currentDistanceInfo->hasLastDabInformation()) { warnKrita << "KisPaintInformation::drawingAngle()" << "Cannot access Distance Info last dab data"; return 0.0; } - return d->currentDistanceInfo->nextDrawingAngle(pos()); + return d()->currentDistanceInfo->nextDrawingAngle(pos()); } void KisPaintInformation::lockCurrentDrawingAngle(qreal alpha_unused) const { Q_UNUSED(alpha_unused); - if (!d->currentDistanceInfo || !d->currentDistanceInfo->hasLastDabInformation()) { + if (!d()->currentDistanceInfo || !d()->currentDistanceInfo->hasLastDabInformation()) { warnKrita << "KisPaintInformation::lockCurrentDrawingAngle()" << "Cannot access Distance Info last dab data"; return; } - qreal angle = d->currentDistanceInfo->nextDrawingAngle(pos(), false); + qreal angle = d()->currentDistanceInfo->nextDrawingAngle(pos(), false); qreal newAngle = angle; - if (d->currentDistanceInfo->hasLockedDrawingAngle()) { + if (d()->currentDistanceInfo->hasLockedDrawingAngle()) { const qreal stabilizingCoeff = 20.0; - const qreal dist = stabilizingCoeff * d->currentDistanceInfo->currentSpacing().scalarApprox(); - const qreal alpha = qMax(0.0, dist - d->currentDistanceInfo->scalarDistanceApprox()) / dist; + const qreal dist = stabilizingCoeff * d()->currentDistanceInfo->currentSpacing().scalarApprox(); + const qreal alpha = qMax(0.0, dist - d()->currentDistanceInfo->scalarDistanceApprox()) / dist; - const qreal oldAngle = d->currentDistanceInfo->lockedDrawingAngle(); + const qreal oldAngle = d()->currentDistanceInfo->lockedDrawingAngle(); if (shortestAngularDistance(oldAngle, newAngle) < M_PI / 6) { newAngle = (1.0 - alpha) * oldAngle + alpha * newAngle; @@ -385,36 +405,36 @@ } } - d->currentDistanceInfo->setLockedDrawingAngle(newAngle); + d()->currentDistanceInfo->setLockedDrawingAngle(newAngle); } QPointF KisPaintInformation::drawingDirectionVector() const { - if (d->drawingAngleOverride) { - qreal angle = *d->drawingAngleOverride; + if (d()->drawingAngleOverride) { + qreal angle = *d()->drawingAngleOverride; return QPointF(cos(angle), sin(angle)); } - if (!d->currentDistanceInfo || !d->currentDistanceInfo->hasLastDabInformation()) { + if (!d()->currentDistanceInfo || !d()->currentDistanceInfo->hasLastDabInformation()) { warnKrita << "KisPaintInformation::drawingDirectionVector()" << "Cannot access Distance Info last dab data"; return QPointF(1.0, 0.0); } - return d->currentDistanceInfo->nextDrawingDirectionVector(pos()); + return d()->currentDistanceInfo->nextDrawingDirectionVector(pos()); } qreal KisPaintInformation::drawingDistance() const { - if (!d->currentDistanceInfo || !d->currentDistanceInfo->hasLastDabInformation()) { + if (!d()->currentDistanceInfo || !d()->currentDistanceInfo->hasLastDabInformation()) { warnKrita << "KisPaintInformation::drawingDistance()" << "Cannot access Distance Info last dab data"; return 1.0; } - QVector2D diff(pos() - d->currentDistanceInfo->lastPosition()); + QVector2D diff(pos() - d()->currentDistanceInfo->lastPosition()); qreal length = diff.length(); - if (d->levelOfDetail) { - length *= KisLodTransform::lodToInvScale(d->levelOfDetail); + if (d()->levelOfDetail) { + length *= KisLodTransform::lodToInvScale(d()->levelOfDetail); } return length; @@ -422,46 +442,46 @@ qreal KisPaintInformation::drawingSpeed() const { - return d->speed; + return d()->speed; } qreal KisPaintInformation::rotation() const { - return d->rotation; + return d()->rotation; } qreal KisPaintInformation::tangentialPressure() const { - return d->tangentialPressure; + return d()->tangentialPressure; } qreal KisPaintInformation::perspective() const { - return d->perspective; + return d()->perspective; } qreal KisPaintInformation::currentTime() const { - return d->time; + return d()->time; } KisRandomSourceSP KisPaintInformation::randomSource() const { - if (!d->randomSource) { - d->randomSource = new KisRandomSource(); + if (!d()->randomSource) { + const_cast(d())->randomSource = new KisRandomSource(); } - return d->randomSource; + return d()->randomSource; } void KisPaintInformation::setRandomSource(KisRandomSourceSP value) { - d->randomSource = value; + d()->randomSource = value; } void KisPaintInformation::setLevelOfDetail(int levelOfDetail) const { - d->levelOfDetail = levelOfDetail; + const_cast(d())->levelOfDetail = levelOfDetail; } QDebug operator<<(QDebug dbg, const KisPaintInformation &info) @@ -549,11 +569,11 @@ KisPaintInformation result(p, pressure, xTilt, yTilt, rotation, tangentialPressure, perspective, time, speed); KIS_ASSERT_RECOVER_NOOP(pi1.isHoveringMode() == pi2.isHoveringMode()); - result.d->isHoveringMode = pi1.isHoveringMode(); - result.d->levelOfDetail = pi1.d->levelOfDetail; - result.d->randomSource = pi1.d->randomSource; - result.d->canvasRotation = pi2.canvasRotation(); - result.d->canvasMirroredH = pi2.canvasMirroredH(); + result.d()->isHoveringMode = pi1.isHoveringMode(); + result.d()->levelOfDetail = pi1.d()->levelOfDetail; + result.d()->randomSource = pi1.d()->randomSource; + result.d()->canvasRotation = pi2.canvasRotation(); + result.d()->canvasMirroredH = pi2.canvasMirroredH(); return result; }