1037 const quint32 bytesPerPaddedScanline = ((bytesPerScanline + 7) / 8) * 8;
1046 scanlines[i] = buffer.data() + i * bytesPerPaddedScanline;
1052 memset(scanlines[i], defaultPixel, bytesPerScanline);
1067 memset(scanlines[i], defaultPixel, bytesPerScanline);
1073 for (
int y = 0; y <
rect.height(); ++y)
1078 std::rotate(std::begin(scanlines), std::begin(scanlines) + 1, std::end(scanlines));
1092 for (
int x = 0; x <
rect.width(); ++x)
1098 const qint32 pixelNW = *(pixelPtrN - 1);
1099 const qint32 pixelN = *(pixelPtrN );
1100 const qint32 pixelNE = *(pixelPtrN + 1);
1101 const qint32 pixelW = *(pixelPtrM - 1);
1102 const qint32 pixelM = *(pixelPtrM );
1103 const qint32 pixelE = *(pixelPtrM + 1);
1104 const qint32 pixelSW = *(pixelPtrS - 1);
1105 const qint32 pixelS = *(pixelPtrS );
1106 const qint32 pixelSE = *(pixelPtrS + 1);
1108 const qint32 rowNSum = (pixelNW >> 2) + (pixelN >> 1) + (pixelNE >> 2);
1109 const qint32 rowMSum = (pixelW >> 2) + (pixelM >> 1) + (pixelE >> 2);
1110 const qint32 rowSSum = (pixelSW >> 2) + (pixelS >> 1) + (pixelSE >> 2);
1111 const qint32 colWSum = (pixelNW >> 2) + (pixelW >> 1) + (pixelSW >> 2);
1112 const qint32 colMSum = (pixelN >> 2) + (pixelM >> 1) + (pixelS >> 2);
1113 const qint32 colESum = (pixelNE >> 2) + (pixelE >> 1) + (pixelSE >> 2);
1114 const qint32 gradientN = qAbs(rowMSum - rowNSum);
1115 const qint32 gradientS = qAbs(rowSSum - rowMSum);
1116 const qint32 gradientW = qAbs(colMSum - colWSum);
1117 const qint32 gradientE = qAbs(colESum - colMSum);
1119 const qint32 maxGradientNS = qMax(gradientN, gradientS);
1120 const qint32 maxGradientWE = qMax(gradientW, gradientE);
1121 const qint32 maxGradient = qMax(maxGradientNS, maxGradientWE);
1125 antialiasedScanline[x] = pixelM;
1129 qint32 neighborPixel, gradient;
1130 qint32 pixelOffset, rowMultiplier, colMultiplier;
1131 if (maxGradientNS > maxGradientWE) {
1133 if (gradientN > gradientS) {
1135 neighborPixel = pixelN;
1136 gradient = gradientN;
1140 neighborPixel = pixelS;
1141 gradient = gradientS;
1148 if (gradientW > gradientE) {
1150 neighborPixel = pixelW;
1151 gradient = gradientW;
1155 neighborPixel = pixelE;
1156 gradient = gradientE;
1163 const qint32 pixelAvg = (neighborPixel + pixelM) >> 1;
1164 const qint32 currentPixelDiff = pixelM - pixelAvg;
1165 qint32 negativePixelDiff, positivePixelDiff;
1166 qint32 negativeSpanEndDistance, positiveSpanEndDistance;
1167 bool negativeSpanExtremeValid, positiveSpanExtremeValid;
1169 rowMultiplier, colMultiplier,
1170 pixelAvg, gradient >> 2, currentPixelDiff,
1171 &negativeSpanEndDistance, &positiveSpanEndDistance,
1172 &negativePixelDiff, &positivePixelDiff,
1173 &negativeSpanExtremeValid, &positiveSpanExtremeValid);
1177 qint32 interpolationValue;
1179 negativePixelDiff, positivePixelDiff, currentPixelDiff,
1180 negativeSpanExtremeValid, positiveSpanExtremeValid, &interpolationValue)) {
1181 antialiasedScanline[x] = pixelM;
1183 antialiasedScanline[x] = neighborPixel + ((pixelM - neighborPixel) * interpolationValue >> 8);
1224 const qint32 maskScanLineSize =
rect.width();
1226 const qint32 referencePixelSize = referenceColorSpace->
pixelSize();
1227 const qint32 referenceScanLineSize = maskScanLineSize * referencePixelSize;
1232 quint8 *maskScanLines[2] = {maskBuffer.data(), maskBuffer.data() + maskScanLineSize};
1233 quint8 *referenceScanLines[2] = {referenceBuffer.data(), referenceBuffer.data() + referenceScanLineSize};
1234 quint8 *selectionScanLine = selectionBuffer.data();
1236 auto testSelectPixel =
1237 [referenceColorSpace]
1238 (quint8 pixelOpacity, quint8 pixelIntensity,
1239 const quint8 *testMaskPixel,
const quint8 *testReferencePixel) ->
bool
1241 if (*testMaskPixel) {
1242 const quint8 testOpacity = referenceColorSpace->
opacityU8(testReferencePixel);
1243 if (pixelOpacity >= testOpacity) {
1251 const quint8 testIntensity = referenceColorSpace->
intensity8(testReferencePixel);
1252 if (pixelIntensity <= testIntensity) {
1263 mask->
readBytes(maskScanLines[1],
rect.left(),
rect.top(), maskScanLineSize, 1);
1265 pixelSelection->
readBytes(selectionScanLine,
rect.left(),
rect.top(), maskScanLineSize, 1);
1266 quint8 *currentMaskScanLineBegin = maskScanLines[1];
1267 quint8 *currentMaskScanLineEnd = maskScanLines[1] + maskScanLineSize;
1268 quint8 *currentReferenceScanLineBegin = referenceScanLines[1];
1269 quint8 *currentSelectionScanLineBegin = selectionScanLine;
1271 ++currentMaskScanLineBegin;
1272 currentReferenceScanLineBegin += referencePixelSize;
1273 ++currentSelectionScanLineBegin;
1275 while (currentMaskScanLineBegin != currentMaskScanLineEnd) {
1277 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1278 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1280 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1281 currentMaskScanLineBegin - 1,
1282 currentReferenceScanLineBegin - referencePixelSize);
1283 if (pixelIsSelected) {
1287 ++currentMaskScanLineBegin;
1288 currentReferenceScanLineBegin += referencePixelSize;
1289 ++currentSelectionScanLineBegin;
1294 for (qint32 y =
rect.top() + 1; y <=
rect.bottom(); ++y) {
1297 mask->
readBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);
1299 pixelSelection->
readBytes(selectionScanLine,
rect.left(), y, maskScanLineSize, 1);
1300 quint8 *currentMaskScanLineBegin = maskScanLines[1];
1301 quint8 *currentMaskScanLineEnd = maskScanLines[1] + maskScanLineSize;
1302 quint8 *currentReferenceScanLineBegin = referenceScanLines[1];
1303 quint8 *topMaskScanLineBegin = maskScanLines[0];
1304 quint8 *topReferenceScanLineBegin = referenceScanLines[0];
1305 quint8 *currentSelectionScanLineBegin = selectionScanLine;
1309 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1310 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1312 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1313 topMaskScanLineBegin,
1314 topReferenceScanLineBegin);
1315 if (!pixelIsSelected) {
1316 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1317 topMaskScanLineBegin + 1,
1318 topReferenceScanLineBegin + referencePixelSize);
1320 if (pixelIsSelected) {
1324 ++currentMaskScanLineBegin;
1325 currentReferenceScanLineBegin += referencePixelSize;
1326 ++topMaskScanLineBegin;
1327 topReferenceScanLineBegin += referencePixelSize;
1328 ++currentSelectionScanLineBegin;
1331 while (currentMaskScanLineBegin != (currentMaskScanLineEnd - 1)) {
1333 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1334 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1336 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1337 topMaskScanLineBegin - 1,
1338 topReferenceScanLineBegin - referencePixelSize);
1339 if (!pixelIsSelected) {
1340 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1341 topMaskScanLineBegin,
1342 topReferenceScanLineBegin);
1343 if (!pixelIsSelected) {
1344 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1345 topMaskScanLineBegin + 1,
1346 topReferenceScanLineBegin + referencePixelSize);
1347 if (!pixelIsSelected) {
1348 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1349 currentMaskScanLineBegin - 1,
1350 currentReferenceScanLineBegin - referencePixelSize);
1354 if (pixelIsSelected) {
1358 ++currentMaskScanLineBegin;
1359 currentReferenceScanLineBegin += referencePixelSize;
1360 ++topMaskScanLineBegin;
1361 topReferenceScanLineBegin += referencePixelSize;
1362 ++currentSelectionScanLineBegin;
1367 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1368 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1370 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1371 topMaskScanLineBegin - 1,
1372 topReferenceScanLineBegin - referencePixelSize);
1373 if (!pixelIsSelected) {
1374 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1375 topMaskScanLineBegin,
1376 topReferenceScanLineBegin);
1377 if (!pixelIsSelected) {
1378 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1379 currentMaskScanLineBegin - 1,
1380 currentReferenceScanLineBegin - referencePixelSize);
1383 if (pixelIsSelected) {
1388 mask->
writeBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);
1394 mask->
readBytes(maskScanLines[1],
rect.left(),
rect.bottom(), maskScanLineSize, 1);
1396 pixelSelection->
readBytes(selectionScanLine,
rect.left(),
rect.bottom(), maskScanLineSize, 1);
1397 quint8 *currentMaskScanLineBegin = maskScanLines[1] + maskScanLineSize - 1;
1398 quint8 *currentMaskScanLineEnd = maskScanLines[1] - 1;
1399 quint8 *currentReferenceScanLineBegin = referenceScanLines[1] + referenceScanLineSize - referencePixelSize;
1400 quint8 *currentSelectionScanLineBegin = selectionScanLine + maskScanLineSize - 1;
1402 --currentMaskScanLineBegin;
1403 currentReferenceScanLineBegin -= referencePixelSize;
1404 --currentSelectionScanLineBegin;
1406 while (currentMaskScanLineBegin != currentMaskScanLineEnd) {
1408 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1409 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1411 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1412 currentMaskScanLineBegin + 1,
1413 currentReferenceScanLineBegin + referencePixelSize);
1414 if (pixelIsSelected) {
1418 --currentMaskScanLineBegin;
1419 currentReferenceScanLineBegin -= referencePixelSize;
1420 --currentSelectionScanLineBegin;
1425 for (qint32 y =
rect.bottom() - 1; y >=
rect.top(); --y) {
1428 mask->
readBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);
1430 pixelSelection->
readBytes(selectionScanLine,
rect.left(), y, maskScanLineSize, 1);
1431 quint8 *currentMaskScanLineBegin = maskScanLines[1] + maskScanLineSize - 1;
1432 quint8 *currentMaskScanLineEnd = maskScanLines[1] - 1;
1433 quint8 *currentReferenceScanLineBegin = referenceScanLines[1] + referenceScanLineSize - referencePixelSize;
1434 quint8 *bottomMaskScanLineBegin = maskScanLines[0] + maskScanLineSize - 1;
1435 quint8 *bottomReferenceScanLineBegin = referenceScanLines[0] + referenceScanLineSize - referencePixelSize;
1436 quint8 *currentSelectionScanLineBegin = selectionScanLine + maskScanLineSize - 1;
1440 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1441 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1443 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1444 bottomMaskScanLineBegin,
1445 bottomReferenceScanLineBegin);
1446 if (!pixelIsSelected) {
1447 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1448 bottomMaskScanLineBegin - 1,
1449 bottomReferenceScanLineBegin - referencePixelSize);
1451 if (pixelIsSelected) {
1455 --currentMaskScanLineBegin;
1456 currentReferenceScanLineBegin -= referencePixelSize;
1457 --bottomMaskScanLineBegin;
1458 bottomReferenceScanLineBegin -= referencePixelSize;
1459 --currentSelectionScanLineBegin;
1462 while (currentMaskScanLineBegin != (currentMaskScanLineEnd + 1)) {
1464 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1465 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1467 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1468 bottomMaskScanLineBegin + 1,
1469 bottomReferenceScanLineBegin + referencePixelSize);
1470 if (!pixelIsSelected) {
1471 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1472 bottomMaskScanLineBegin,
1473 bottomReferenceScanLineBegin);
1474 if (!pixelIsSelected) {
1475 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1476 bottomMaskScanLineBegin - 1,
1477 bottomReferenceScanLineBegin - referencePixelSize);
1478 if (!pixelIsSelected) {
1479 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1480 currentMaskScanLineBegin + 1,
1481 currentReferenceScanLineBegin + referencePixelSize);
1485 if (pixelIsSelected) {
1489 --currentMaskScanLineBegin;
1490 currentReferenceScanLineBegin -= referencePixelSize;
1491 --bottomMaskScanLineBegin;
1492 bottomReferenceScanLineBegin -= referencePixelSize;
1493 --currentSelectionScanLineBegin;
1498 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1499 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1501 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1502 bottomMaskScanLineBegin + 1,
1503 bottomReferenceScanLineBegin + referencePixelSize);
1504 if (!pixelIsSelected) {
1505 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1506 bottomMaskScanLineBegin,
1507 bottomReferenceScanLineBegin);
1508 if (!pixelIsSelected) {
1509 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1510 currentMaskScanLineBegin + 1,
1511 currentReferenceScanLineBegin + referencePixelSize);
1514 if (pixelIsSelected) {
1519 mask->
writeBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);