Commit b4347512 authored by Ivan Yossi's avatar Ivan Yossi 👌

Fix 1px brush offset in line tool

This adjust the diferent position of KisPaintInformation
from a line to be inside a line between starting and
ending points. This is particularly important as brushes
that use 1px perfect pixels require the line to be perfect
in order to avoid looking jagged. In 1px size with
sharpen active we only use the start and end
KisPaintInformation points.

This patch also adjusts the outine on 1px brushes to
adjust to the grid to better preview where the paint is
going to be applyied

BUG:407405
parent f2419f5a
......@@ -22,7 +22,7 @@
#include "kis_paintop.h"
#include <math.h>
#include <QtMath>
#include <KoColor.h>
#include <KoColorSpace.h>
......@@ -96,7 +96,7 @@ void KisPaintOp::setFanCornersInfo(bool fanCornersEnabled, qreal fanCornersStep)
void KisPaintOp::splitCoordinate(qreal coordinate, qint32 *whole, qreal *fraction)
{
const qint32 i = std::floor(coordinate);
const qint32 i = qFloor(coordinate);
const qreal f = coordinate - i;
*whole = i;
......
......@@ -1655,7 +1655,15 @@ void KisPainter::drawDDALine(const QPointF & start, const QPointF & end)
int xd = x2 - x;
int yd = y2 - y;
float m = (float)yd / (float)xd;
float m = 0;
bool lockAxis = true;
if (xd == 0) {
m = 2.0;
} else if ( yd != 0) {
lockAxis = false;
m = (float)yd / (float)xd;
}
float fx = x;
float fy = y;
......@@ -1677,7 +1685,7 @@ void KisPainter::drawDDALine(const QPointF & start, const QPointF & end)
if (fabs(m) > 1.0f) {
inc = (yd > 0) ? 1 : -1;
m = 1.0f / m;
m = (lockAxis)? 0 : 1.0f / m;
m *= inc;
while (y != y2) {
y = y + inc;
......
......@@ -27,6 +27,7 @@
#include "kis_signals_blocker.h"
#include "kis_brush_option.h"
#include <KisPaintopSettingsIds.h>
#include <brushengine/kis_paintop_preset.h>
struct BrushReader {
BrushReader(const KisBrushBasedPaintOpSettings *parent)
......@@ -66,7 +67,9 @@ struct BrushWriter {
KisBrushBasedPaintOpSettings::KisBrushBasedPaintOpSettings()
: KisOutlineGenerationPolicy<KisPaintOpSettings>(KisCurrentOutlineFetcher::SIZE_OPTION |
KisCurrentOutlineFetcher::ROTATION_OPTION |
KisCurrentOutlineFetcher::MIRROR_OPTION)
KisCurrentOutlineFetcher::MIRROR_OPTION |
KisCurrentOutlineFetcher::SHARPNESS_OPTION)
{
}
......
......@@ -21,6 +21,7 @@
#include "kis_pressure_size_option.h"
#include "kis_pressure_rotation_option.h"
#include "kis_pressure_mirror_option.h"
#include "kis_pressure_sharpness_option.h"
#include <brushengine/kis_paintop_settings.h>
#include <kis_properties_configuration.h>
#include "kis_paintop_settings.h"
......@@ -42,11 +43,16 @@ struct KisCurrentOutlineFetcher::Private {
if (optionsAvailable & MIRROR_OPTION) {
mirrorOption.reset(new KisPressureMirrorOption());
}
if (optionsAvailable & SHARPNESS_OPTION) {
sharpnessOption.reset(new KisPressureSharpnessOption());
}
}
QScopedPointer<KisPressureSizeOption> sizeOption;
QScopedPointer<KisPressureRotationOption> rotationOption;
QScopedPointer<KisPressureMirrorOption> mirrorOption;
QScopedPointer<KisPressureSharpnessOption> sharpnessOption;
bool isDirty;
QElapsedTimer lastUpdateTime;
......@@ -95,6 +101,11 @@ QPainterPath KisCurrentOutlineFetcher::fetchOutline(const KisPaintInformation &i
d->mirrorOption->resetAllSensors();
}
if (d->sharpnessOption) {
d->sharpnessOption->readOptionSetting(settings);
d->sharpnessOption->resetAllSensors();
}
d->isDirty = false;
}
......@@ -145,7 +156,6 @@ QPainterPath KisCurrentOutlineFetcher::fetchOutline(const KisPaintInformation &i
}
}
QTransform rot;
rot.rotateRadians(-rotation);
......@@ -154,8 +164,17 @@ QPainterPath KisCurrentOutlineFetcher::fetchOutline(const KisPaintInformation &i
hotSpot.setX(tiltcenterx);
hotSpot.setY(tiltcentery);
}
QPointF pos = info.pos();
if (d->sharpnessOption) {
qint32 x = 0, y = 0;
qreal subPixelX = 0.0, subPixelY = 0.0;
d->sharpnessOption->apply(info, pos - hotSpot, x, y, subPixelX, subPixelY);
pos = QPointF(x + subPixelX, y + subPixelY) + hotSpot;
}
QTransform T1 = QTransform::fromTranslate(-hotSpot.x(), -hotSpot.y());
QTransform T2 = QTransform::fromTranslate(info.pos().x(), info.pos().y());
QTransform T2 = QTransform::fromTranslate(pos.x(), pos.y());
QTransform S = QTransform::fromScale(xFlip * scale, yFlip * scale);
return (T1 * rot * S * T2).map(originalOutline);
......
......@@ -39,7 +39,8 @@ public:
NO_OPTION,
SIZE_OPTION,
ROTATION_OPTION,
MIRROR_OPTION
MIRROR_OPTION,
SHARPNESS_OPTION
};
Q_DECLARE_FLAGS(Options, Option);
......
......@@ -18,10 +18,15 @@
#include "kis_tool_line_helper.h"
#include <QtMath>
#include "kis_algebra_2d.h"
#include "kis_painting_information_builder.h"
#include "kis_image.h"
#include "kis_canvas_resource_provider.h"
#include <brushengine/kis_paintop_preset.h>
struct KisToolLineHelper::Private
{
Private(KisPaintingInformationBuilder *_infoBuilder)
......@@ -77,6 +82,20 @@ void KisToolLineHelper::repaintLine(KoCanvasResourceProvider *resourceManager,
0.0);
}
KisPaintOpPresetSP preset = resourceManager->resource(KisCanvasResourceProvider::CurrentPaintOpPreset)
.value<KisPaintOpPresetSP>();
if (preset->settings()->paintOpSize() <= 1) {
KisPaintInformation begin = m_d->linePoints.first();
KisPaintInformation end = m_d->linePoints.last();
m_d->linePoints.clear();
m_d->linePoints.append(begin);
m_d->linePoints.append(end);
}
// Always adjust line sections to avoid jagged sections.
adjustPointsToDDA(m_d->linePoints);
QVector<KisPaintInformation>::const_iterator it = m_d->linePoints.constBegin();
QVector<KisPaintInformation>::const_iterator end = m_d->linePoints.constEnd();
......@@ -188,3 +207,56 @@ void KisToolLineHelper::clearPaint()
cancelPaint();
}
void KisToolLineHelper::adjustPointsToDDA(QVector<KisPaintInformation> &points)
{
int x = qFloor(points.first().pos().x());
int y = qFloor(points.first().pos().y());
int x2 = qFloor(points.last().pos().x());
int y2 = qFloor(points.last().pos().y());
// Width and height of the line
int xd = x2 - x;
int yd = y2 - y;
float m = 0;
bool lockAxis = true;
if (xd == 0) {
m = 2.0;
} else if ( yd != 0) {
lockAxis = false;
m = (float)yd / (float)xd;
}
float fx = x;
float fy = y;
int inc;
int dist;
if (fabs(m) > 1.0f) {
inc = (yd > 0) ? 1 : -1;
m = (lockAxis)? 0 : 1.0f / m;
m *= inc;
for (int i = 0; i < points.size(); i++){
dist = abs(qFloor(points.at(i).pos().y()) - y);
fy = y + (dist * inc);
fx = qRound(x + (dist * m));
points[i].setPos(QPointF(fx,fy));
}
} else {
inc = (xd > 0) ? 1 : -1;
m *= inc;
for (int i = 0; i < points.size(); i++){
dist = abs(qFloor(points.at(i).pos().x()) - x);
fx = x + (dist * inc);
fy = qRound(y + (dist * m));
points[i].setPos(QPointF(fx,fy));
}
}
}
......@@ -48,6 +48,9 @@ public:
using KisToolFreehandHelper::isRunning;
private:
void adjustPointsToDDA(QVector<KisPaintInformation> &points);
private:
struct Private;
Private * const m_d;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment