1032 const quint32 bytesPerPaddedScanline = ((bytesPerScanline + 7) / 8) * 8;
1041 scanlines[i] = buffer.data() + i * bytesPerPaddedScanline;
1047 memset(scanlines[i], defaultPixel, bytesPerScanline);
1062 memset(scanlines[i], defaultPixel, bytesPerScanline);
1068 for (
int y = 0; y <
rect.height(); ++y)
1073 std::rotate(std::begin(scanlines), std::begin(scanlines) + 1, std::end(scanlines));
1087 for (
int x = 0; x <
rect.width(); ++x)
1093 const qint32 pixelNW = *(pixelPtrN - 1);
1094 const qint32 pixelN = *(pixelPtrN );
1095 const qint32 pixelNE = *(pixelPtrN + 1);
1096 const qint32 pixelW = *(pixelPtrM - 1);
1097 const qint32 pixelM = *(pixelPtrM );
1098 const qint32 pixelE = *(pixelPtrM + 1);
1099 const qint32 pixelSW = *(pixelPtrS - 1);
1100 const qint32 pixelS = *(pixelPtrS );
1101 const qint32 pixelSE = *(pixelPtrS + 1);
1103 const qint32 rowNSum = (pixelNW >> 2) + (pixelN >> 1) + (pixelNE >> 2);
1104 const qint32 rowMSum = (pixelW >> 2) + (pixelM >> 1) + (pixelE >> 2);
1105 const qint32 rowSSum = (pixelSW >> 2) + (pixelS >> 1) + (pixelSE >> 2);
1106 const qint32 colWSum = (pixelNW >> 2) + (pixelW >> 1) + (pixelSW >> 2);
1107 const qint32 colMSum = (pixelN >> 2) + (pixelM >> 1) + (pixelS >> 2);
1108 const qint32 colESum = (pixelNE >> 2) + (pixelE >> 1) + (pixelSE >> 2);
1109 const qint32 gradientN = qAbs(rowMSum - rowNSum);
1110 const qint32 gradientS = qAbs(rowSSum - rowMSum);
1111 const qint32 gradientW = qAbs(colMSum - colWSum);
1112 const qint32 gradientE = qAbs(colESum - colMSum);
1114 const qint32 maxGradientNS = qMax(gradientN, gradientS);
1115 const qint32 maxGradientWE = qMax(gradientW, gradientE);
1116 const qint32 maxGradient = qMax(maxGradientNS, maxGradientWE);
1120 antialiasedScanline[x] = pixelM;
1124 qint32 neighborPixel, gradient;
1125 qint32 pixelOffset, rowMultiplier, colMultiplier;
1126 if (maxGradientNS > maxGradientWE) {
1128 if (gradientN > gradientS) {
1130 neighborPixel = pixelN;
1131 gradient = gradientN;
1135 neighborPixel = pixelS;
1136 gradient = gradientS;
1143 if (gradientW > gradientE) {
1145 neighborPixel = pixelW;
1146 gradient = gradientW;
1150 neighborPixel = pixelE;
1151 gradient = gradientE;
1158 const qint32 pixelAvg = (neighborPixel + pixelM) >> 1;
1159 const qint32 currentPixelDiff = pixelM - pixelAvg;
1160 qint32 negativePixelDiff, positivePixelDiff;
1161 qint32 negativeSpanEndDistance, positiveSpanEndDistance;
1162 bool negativeSpanExtremeValid, positiveSpanExtremeValid;
1164 rowMultiplier, colMultiplier,
1165 pixelAvg, gradient >> 2, currentPixelDiff,
1166 &negativeSpanEndDistance, &positiveSpanEndDistance,
1167 &negativePixelDiff, &positivePixelDiff,
1168 &negativeSpanExtremeValid, &positiveSpanExtremeValid);
1172 qint32 interpolationValue;
1174 negativePixelDiff, positivePixelDiff, currentPixelDiff,
1175 negativeSpanExtremeValid, positiveSpanExtremeValid, &interpolationValue)) {
1176 antialiasedScanline[x] = pixelM;
1178 antialiasedScanline[x] = neighborPixel + ((pixelM - neighborPixel) * interpolationValue >> 8);
1219 const qint32 maskScanLineSize =
rect.width();
1221 const qint32 referencePixelSize = referenceColorSpace->
pixelSize();
1222 const qint32 referenceScanLineSize = maskScanLineSize * referencePixelSize;
1227 quint8 *maskScanLines[2] = {maskBuffer.data(), maskBuffer.data() + maskScanLineSize};
1228 quint8 *referenceScanLines[2] = {referenceBuffer.data(), referenceBuffer.data() + referenceScanLineSize};
1229 quint8 *selectionScanLine = selectionBuffer.data();
1231 auto testSelectPixel =
1232 [referenceColorSpace]
1233 (quint8 pixelOpacity, quint8 pixelIntensity,
1234 const quint8 *testMaskPixel,
const quint8 *testReferencePixel) ->
bool
1236 if (*testMaskPixel) {
1237 const quint8 testOpacity = referenceColorSpace->
opacityU8(testReferencePixel);
1238 if (pixelOpacity >= testOpacity) {
1246 const quint8 testIntensity = referenceColorSpace->
intensity8(testReferencePixel);
1247 if (pixelIntensity <= testIntensity) {
1258 mask->
readBytes(maskScanLines[1],
rect.left(),
rect.top(), maskScanLineSize, 1);
1260 pixelSelection->
readBytes(selectionScanLine,
rect.left(),
rect.top(), maskScanLineSize, 1);
1261 quint8 *currentMaskScanLineBegin = maskScanLines[1];
1262 quint8 *currentMaskScanLineEnd = maskScanLines[1] + maskScanLineSize;
1263 quint8 *currentReferenceScanLineBegin = referenceScanLines[1];
1264 quint8 *currentSelectionScanLineBegin = selectionScanLine;
1266 ++currentMaskScanLineBegin;
1267 currentReferenceScanLineBegin += referencePixelSize;
1268 ++currentSelectionScanLineBegin;
1270 while (currentMaskScanLineBegin != currentMaskScanLineEnd) {
1272 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1273 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1275 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1276 currentMaskScanLineBegin - 1,
1277 currentReferenceScanLineBegin - referencePixelSize);
1278 if (pixelIsSelected) {
1282 ++currentMaskScanLineBegin;
1283 currentReferenceScanLineBegin += referencePixelSize;
1284 ++currentSelectionScanLineBegin;
1289 for (qint32 y =
rect.top() + 1; y <=
rect.bottom(); ++y) {
1292 mask->
readBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);
1294 pixelSelection->
readBytes(selectionScanLine,
rect.left(), y, maskScanLineSize, 1);
1295 quint8 *currentMaskScanLineBegin = maskScanLines[1];
1296 quint8 *currentMaskScanLineEnd = maskScanLines[1] + maskScanLineSize;
1297 quint8 *currentReferenceScanLineBegin = referenceScanLines[1];
1298 quint8 *topMaskScanLineBegin = maskScanLines[0];
1299 quint8 *topReferenceScanLineBegin = referenceScanLines[0];
1300 quint8 *currentSelectionScanLineBegin = selectionScanLine;
1304 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1305 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1307 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1308 topMaskScanLineBegin,
1309 topReferenceScanLineBegin);
1310 if (!pixelIsSelected) {
1311 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1312 topMaskScanLineBegin + 1,
1313 topReferenceScanLineBegin + referencePixelSize);
1315 if (pixelIsSelected) {
1319 ++currentMaskScanLineBegin;
1320 currentReferenceScanLineBegin += referencePixelSize;
1321 ++topMaskScanLineBegin;
1322 topReferenceScanLineBegin += referencePixelSize;
1323 ++currentSelectionScanLineBegin;
1326 while (currentMaskScanLineBegin != (currentMaskScanLineEnd - 1)) {
1328 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1329 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1331 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1332 topMaskScanLineBegin - 1,
1333 topReferenceScanLineBegin - referencePixelSize);
1334 if (!pixelIsSelected) {
1335 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1336 topMaskScanLineBegin,
1337 topReferenceScanLineBegin);
1338 if (!pixelIsSelected) {
1339 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1340 topMaskScanLineBegin + 1,
1341 topReferenceScanLineBegin + referencePixelSize);
1342 if (!pixelIsSelected) {
1343 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1344 currentMaskScanLineBegin - 1,
1345 currentReferenceScanLineBegin - referencePixelSize);
1349 if (pixelIsSelected) {
1353 ++currentMaskScanLineBegin;
1354 currentReferenceScanLineBegin += referencePixelSize;
1355 ++topMaskScanLineBegin;
1356 topReferenceScanLineBegin += referencePixelSize;
1357 ++currentSelectionScanLineBegin;
1362 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1363 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1365 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1366 topMaskScanLineBegin - 1,
1367 topReferenceScanLineBegin - referencePixelSize);
1368 if (!pixelIsSelected) {
1369 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1370 topMaskScanLineBegin,
1371 topReferenceScanLineBegin);
1372 if (!pixelIsSelected) {
1373 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1374 currentMaskScanLineBegin - 1,
1375 currentReferenceScanLineBegin - referencePixelSize);
1378 if (pixelIsSelected) {
1383 mask->
writeBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);
1389 mask->
readBytes(maskScanLines[1],
rect.left(),
rect.bottom(), maskScanLineSize, 1);
1391 pixelSelection->
readBytes(selectionScanLine,
rect.left(),
rect.bottom(), maskScanLineSize, 1);
1392 quint8 *currentMaskScanLineBegin = maskScanLines[1] + maskScanLineSize - 1;
1393 quint8 *currentMaskScanLineEnd = maskScanLines[1] - 1;
1394 quint8 *currentReferenceScanLineBegin = referenceScanLines[1] + referenceScanLineSize - referencePixelSize;
1395 quint8 *currentSelectionScanLineBegin = selectionScanLine + maskScanLineSize - 1;
1397 --currentMaskScanLineBegin;
1398 currentReferenceScanLineBegin -= referencePixelSize;
1399 --currentSelectionScanLineBegin;
1401 while (currentMaskScanLineBegin != currentMaskScanLineEnd) {
1403 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1404 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1406 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1407 currentMaskScanLineBegin + 1,
1408 currentReferenceScanLineBegin + referencePixelSize);
1409 if (pixelIsSelected) {
1413 --currentMaskScanLineBegin;
1414 currentReferenceScanLineBegin -= referencePixelSize;
1415 --currentSelectionScanLineBegin;
1420 for (qint32 y =
rect.bottom() - 1; y >=
rect.top(); --y) {
1423 mask->
readBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);
1425 pixelSelection->
readBytes(selectionScanLine,
rect.left(), y, maskScanLineSize, 1);
1426 quint8 *currentMaskScanLineBegin = maskScanLines[1] + maskScanLineSize - 1;
1427 quint8 *currentMaskScanLineEnd = maskScanLines[1] - 1;
1428 quint8 *currentReferenceScanLineBegin = referenceScanLines[1] + referenceScanLineSize - referencePixelSize;
1429 quint8 *bottomMaskScanLineBegin = maskScanLines[0] + maskScanLineSize - 1;
1430 quint8 *bottomReferenceScanLineBegin = referenceScanLines[0] + referenceScanLineSize - referencePixelSize;
1431 quint8 *currentSelectionScanLineBegin = selectionScanLine + maskScanLineSize - 1;
1435 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1436 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1438 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1439 bottomMaskScanLineBegin,
1440 bottomReferenceScanLineBegin);
1441 if (!pixelIsSelected) {
1442 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1443 bottomMaskScanLineBegin - 1,
1444 bottomReferenceScanLineBegin - referencePixelSize);
1446 if (pixelIsSelected) {
1450 --currentMaskScanLineBegin;
1451 currentReferenceScanLineBegin -= referencePixelSize;
1452 --bottomMaskScanLineBegin;
1453 bottomReferenceScanLineBegin -= referencePixelSize;
1454 --currentSelectionScanLineBegin;
1457 while (currentMaskScanLineBegin != (currentMaskScanLineEnd + 1)) {
1459 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1460 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1462 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1463 bottomMaskScanLineBegin + 1,
1464 bottomReferenceScanLineBegin + referencePixelSize);
1465 if (!pixelIsSelected) {
1466 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1467 bottomMaskScanLineBegin,
1468 bottomReferenceScanLineBegin);
1469 if (!pixelIsSelected) {
1470 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1471 bottomMaskScanLineBegin - 1,
1472 bottomReferenceScanLineBegin - referencePixelSize);
1473 if (!pixelIsSelected) {
1474 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1475 currentMaskScanLineBegin + 1,
1476 currentReferenceScanLineBegin + referencePixelSize);
1480 if (pixelIsSelected) {
1484 --currentMaskScanLineBegin;
1485 currentReferenceScanLineBegin -= referencePixelSize;
1486 --bottomMaskScanLineBegin;
1487 bottomReferenceScanLineBegin -= referencePixelSize;
1488 --currentSelectionScanLineBegin;
1493 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1494 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1496 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1497 bottomMaskScanLineBegin + 1,
1498 bottomReferenceScanLineBegin + referencePixelSize);
1499 if (!pixelIsSelected) {
1500 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1501 bottomMaskScanLineBegin,
1502 bottomReferenceScanLineBegin);
1503 if (!pixelIsSelected) {
1504 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1505 currentMaskScanLineBegin + 1,
1506 currentReferenceScanLineBegin + referencePixelSize);
1509 if (pixelIsSelected) {
1514 mask->
writeBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);