Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LF-54320 hatch pattern when line width small #21

Open
wants to merge 1 commit into
base: 6.5.3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
238 changes: 2 additions & 236 deletions src/gui/painting/qcosmeticstroker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include "private/qpainterpath_p.h"
#include "private/qrgba64_p.h"
#include <qdebug.h>
#include <QtCore/qmath.h>

QT_BEGIN_NAMESPACE

Expand All @@ -29,9 +28,7 @@ typedef qint64 FDot16;
typedef int FDot16;
#endif

#define toF26Dot6(x) static_cast<int>((x) * 64.)
#define toF16Dot16(x) static_cast<int>((x) * 65536.)

#define toF26Dot6(x) static_cast<int>((x) * 64.)

static inline uint sourceOver(uint d, uint color)
{
Expand Down Expand Up @@ -100,61 +97,6 @@ struct Dasher {
}
};

struct FixedDasher
{
QCosmeticStroker *stroker;
int *pattern;
qlonglong offset;
int dashIndex;
int dashOn;
int seenOn = 0;
int dashInc;

FixedDasher(QCosmeticStroker *s, bool reverse, int start, int stop, int dash_offset,
int dash_inc)
: stroker(s), dashInc(dash_inc)
{
int delta = stop - start;
if (reverse) {
pattern = stroker->reversePattern;
offset = qlonglong(stroker->patternOffset - dash_offset) << 10;
dashOn = 0;
} else {
pattern = stroker->pattern;
offset = qlonglong(stroker->patternOffset + dash_offset) << 10;
dashOn = 1;
}
offset %= qlonglong(stroker->patternLength) << 10;
if (offset < 0)
offset += qlonglong(stroker->patternLength) << 10;

dashIndex = 0;
while (offset >= qlonglong(pattern[dashIndex]) << 10)
++dashIndex;

// qDebug() << " dasher" << offset / 64. << reverse << dashIndex << offset << stroker->patternLength;
stroker->patternOffset += delta;
stroker->patternOffset %= stroker->patternLength;
}

bool on() const { return seenOn | ((dashIndex + dashOn) & 1); }
void adjust()
{
offset += dashInc;
seenOn = 0;
while (offset >= qlonglong(pattern[dashIndex]) << 10) {
if (++dashIndex == stroker->patternSize) {
dashIndex = 0;
offset %= qlonglong(stroker->patternLength) << 10;
}
// If we see any on dashes, mark it as on
if ((dashIndex + dashOn) & 1) {
seenOn = 1;
}
}
}
};

struct NoDasher {
NoDasher(QCosmeticStroker *, bool, int, int) {}
bool on() const { return true; }
Expand All @@ -172,9 +114,6 @@ template<DrawPixel drawPixel, class Dasher>
static bool drawLine(QCosmeticStroker *stroker, qreal x1, qreal y1, qreal x2, qreal y2, int caps);
template<DrawPixel drawPixel, class Dasher>
static bool drawLineAA(QCosmeticStroker *stroker, qreal x1, qreal y1, qreal x2, qreal y2, int caps);
template<DrawPixel drawPixel>
static bool drawLineAAFixed(QCosmeticStroker *stroker, qreal x1, qreal y1, qreal x2, qreal y2, int caps);


inline void drawPixel(QCosmeticStroker *stroker, int x, int y, int coverage)
{
Expand Down Expand Up @@ -226,8 +165,7 @@ enum StrokeSelection {
Solid = 0,
Dashed = 2,
RegularDraw = 0,
FastDraw = 4,
FixedDraw = 8,
FastDraw = 4
};

static StrokeLine strokeLine(int strokeSelection)
Expand All @@ -248,11 +186,9 @@ static StrokeLine strokeLine(int strokeSelection)
stroke = &QT_PREPEND_NAMESPACE(drawLine)<drawPixelARGB32Opaque, Dasher>;
break;
case AntiAliased|Solid|RegularDraw:
case AntiAliased|Solid|RegularDraw|FixedDraw:
stroke = &QT_PREPEND_NAMESPACE(drawLineAA)<drawPixel, NoDasher>;
break;
case AntiAliased|Solid|FastDraw:
case AntiAliased|Solid|FastDraw|FixedDraw:
stroke = &QT_PREPEND_NAMESPACE(drawLineAA)<drawPixelARGB32, NoDasher>;
break;
case AntiAliased|Dashed|RegularDraw:
Expand All @@ -261,12 +197,6 @@ static StrokeLine strokeLine(int strokeSelection)
case AntiAliased|Dashed|FastDraw:
stroke = &QT_PREPEND_NAMESPACE(drawLineAA)<drawPixelARGB32, Dasher>;
break;
case AntiAliased|Dashed|RegularDraw|FixedDraw:
stroke = &QT_PREPEND_NAMESPACE(drawLineAAFixed)<drawPixel>;
break;
case AntiAliased|Dashed|FastDraw|FixedDraw:
stroke = &QT_PREPEND_NAMESPACE(drawLineAAFixed)<drawPixelARGB32>;
break;
default:
Q_ASSERT(false);
stroke = nullptr;
Expand All @@ -292,8 +222,6 @@ void QCosmeticStroker::setup()

if (state->renderHints & QPainter::Antialiasing)
strokeSelection |= AntiAliased;
if (state->renderHints & QPainter::FixedDraw) // Magic Seequent-specific render hint
strokeSelection |= FixedDraw;

const QList<qreal> &penPattern = state->lastPen.dashPattern();
if (penPattern.isEmpty() || penPattern.size() > 1024) {
Expand Down Expand Up @@ -1122,166 +1050,4 @@ static bool drawLineAA(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx
return true;
}

static int calculateDashOffset(qreal major1, qreal major2, qreal minor1, qreal minor2)
{
return toF26Dot6(qSqrt((major2 - major1) * (major2 - major1) + (minor2 - minor1) * (minor2 - minor1)));
}

template<DrawPixel drawPixel>
static bool drawLineAAFixed(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, qreal ry2,
int caps)
{
if (stroker->clipLine(rx1, ry1, rx2, ry2))
return true;

qreal oldx1 = rx1;
qreal oldx2 = rx2;
qreal oldy1 = ry1;
qreal oldy2 = ry2;

int offset = 0;

int x1 = toF26Dot6(rx1);
int y1 = toF26Dot6(ry1);
int x2 = toF26Dot6(rx2);
int y2 = toF26Dot6(ry2);

int dx = x2 - x1;
int dy = y2 - y1;

if (qAbs(dx) < qAbs(dy)) {
// vertical

FDot16 xinc = FDot16FixedDiv(dx, dy);

bool swapped = false;
if (y1 > y2) {
qSwap(y1, y2);
qSwap(x1, x2);
swapped = true;
caps = swapCaps(caps);
offset = calculateDashOffset(oldy1, ry2, oldx1, rx2);
} else
offset = calculateDashOffset(oldy1, ry1, oldx1, rx1);

FDot16 x = FDot16(x1 - 32) * (1 << 10);
x -= (((y1 & 63) - 32) * xinc) >> 6;

capAdjust(caps, y1, y2, x, xinc);

FixedDasher dasher(
stroker, swapped, y1, y2, offset,
toF16Dot16(qSqrt(
1 + ((qreal)qAbs(xinc) / (1 << 16)) * ((qreal)qAbs(xinc) / (1 << 16)))));

int y = y1 >> 6;
int ys = y2 >> 6;

int alphaStart, alphaEnd;
if (y == ys) {
alphaStart = y2 - y1;
Q_ASSERT(alphaStart >= 0 && alphaStart < 64);
alphaEnd = 0;
} else {
alphaStart = 64 - (y1 & 63);
alphaEnd = (y2 & 63);
}

// draw first pixel
if (dasher.on()) {
uint alpha = static_cast<quint8>(x >> 8);
drawPixel(stroker, x >> 16, y, (255 - alpha) * alphaStart >> 6);
drawPixel(stroker, (x >> 16) + 1, y, alpha * alphaStart >> 6);
}
dasher.adjust();
x += xinc;
++y;
if (y < ys) {
do {
if (dasher.on()) {
uint alpha = static_cast<quint8>(x >> 8);
drawPixel(stroker, x >> 16, y, (255 - alpha));
drawPixel(stroker, (x >> 16) + 1, y, alpha);
}
dasher.adjust();
x += xinc;
} while (++y < ys);
}
// draw last pixel
if (alphaEnd && dasher.on()) {
uint alpha = static_cast<quint8>(x >> 8);
drawPixel(stroker, x >> 16, y, (255 - alpha) * alphaEnd >> 6);
drawPixel(stroker, (x >> 16) + 1, y, alpha * alphaEnd >> 6);
}
} else {
// horizontal
if (!dx)
return true;

FDot16 yinc = FDot16FixedDiv(dy, dx);

bool swapped = false;
if (x1 > x2) {
qSwap(x1, x2);
qSwap(y1, y2);
swapped = true;
caps = swapCaps(caps);
offset = calculateDashOffset(oldx1, rx2, oldy1, ry2);
} else
offset = calculateDashOffset(oldx1, rx1, oldy1, ry1);

FDot16 y = FDot16(y1 - 32) * (1 << 10);
y -= (((x1 & 63) - 32) * yinc) >> 6;

capAdjust(caps, x1, x2, y, yinc);

FixedDasher dasher(
stroker, swapped, x1, x2, offset,
toF16Dot16(qSqrt(
1 + ((qreal)qAbs(yinc) / (1 << 16)) * ((qreal)qAbs(yinc) / (1 << 16)))));

int x = x1 >> 6;
int xs = x2 >> 6;

int alphaStart, alphaEnd;
if (x == xs) {
alphaStart = x2 - x1;
Q_ASSERT(alphaStart >= 0 && alphaStart < 64);
alphaEnd = 0;
} else {
alphaStart = 64 - (x1 & 63);
alphaEnd = (x2 & 63);
}

// draw first pixel
if (dasher.on()) {
uint alpha = static_cast<quint8>(y >> 8);
drawPixel(stroker, x, y>>16, (255-alpha) * alphaStart >> 6);
drawPixel(stroker, x, (y>>16) + 1, alpha * alphaStart >> 6);
}
dasher.adjust();
y += yinc;
++x;
// draw line
if (x < xs) {
do {
if (dasher.on()) {
uint alpha = static_cast<quint8>(y >> 8);
drawPixel(stroker, x, y>>16, (255-alpha));
drawPixel(stroker, x, (y>>16) + 1, alpha);
}
dasher.adjust();
y += yinc;
} while (++x < xs);
}
// draw last pixel
if (alphaEnd && dasher.on()) {
uint alpha = static_cast<quint8>(y >> 8);
drawPixel(stroker, x, y>>16, (255-alpha) * alphaEnd >> 6);
drawPixel(stroker, x, (y>>16) + 1, alpha * alphaEnd >> 6);
}
}
return true;
}

QT_END_NAMESPACE
3 changes: 2 additions & 1 deletion src/gui/painting/qpaintengine_raster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,8 @@ void QRasterPaintEngine::updatePen(const QPen &pen)

ensureRasterState(); // needed because of tx_noshear...
bool cosmetic = pen.isCosmetic();
s->flags.fast_pen = pen_style > Qt::NoPen
bool fast_dash = !s->renderHints.testFlag(QPainter::FixedDraw);
s->flags.fast_pen = (pen_style == Qt::SolidLine || (pen_style > Qt::SolidLine && fast_dash))
&& s->penData.blend
&& ((cosmetic && penWidth <= 1)
|| (!cosmetic && (s->flags.tx_noshear || !s->flags.antialiased) && penWidth * s->txscale <= 1));
Expand Down