Allow rounding with different radius per corner.
This commit is contained in:
parent
80445f2bd3
commit
f49ec866c1
1 changed files with 41 additions and 27 deletions
|
|
@ -1017,13 +1017,8 @@ QImage Round(
|
||||||
} else {
|
} else {
|
||||||
Assert(QRect(QPoint(), image.size()).contains(target));
|
Assert(QRect(QPoint(), image.size()).contains(target));
|
||||||
}
|
}
|
||||||
auto cornerWidth = cornerMasks[0].width();
|
const auto targetWidth = target.width();
|
||||||
auto cornerHeight = cornerMasks[0].height();
|
const auto targetHeight = target.height();
|
||||||
auto targetWidth = target.width();
|
|
||||||
auto targetHeight = target.height();
|
|
||||||
if (targetWidth < cornerWidth || targetHeight < cornerHeight) {
|
|
||||||
return std::move(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
image = std::move(image).convertToFormat(
|
image = std::move(image).convertToFormat(
|
||||||
QImage::Format_ARGB32_Premultiplied);
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
|
|
@ -1035,40 +1030,59 @@ QImage Round(
|
||||||
// Real image bytesPerLine is smaller than the one we use for offsets.
|
// Real image bytesPerLine is smaller than the one we use for offsets.
|
||||||
auto ints = reinterpret_cast<uint32*>(image.bits());
|
auto ints = reinterpret_cast<uint32*>(image.bits());
|
||||||
|
|
||||||
constexpr auto imageIntsPerPixel = 1;
|
constexpr auto kImageIntsPerPixel = 1;
|
||||||
auto imageIntsPerLine = (image.bytesPerLine() >> 2);
|
const auto imageIntsPerLine = (image.bytesPerLine() >> 2);
|
||||||
Assert(image.depth() == static_cast<int>((imageIntsPerPixel * sizeof(uint32)) << 3));
|
Assert(image.depth() == ((kImageIntsPerPixel * sizeof(uint32)) << 3));
|
||||||
Assert(image.bytesPerLine() == (imageIntsPerLine << 2));
|
Assert(image.bytesPerLine() == (imageIntsPerLine << 2));
|
||||||
auto intsTopLeft = ints + target.x() + target.y() * imageIntsPerLine;
|
const auto maskCorner = [&](
|
||||||
auto intsTopRight = ints + target.x() + targetWidth - cornerWidth + target.y() * imageIntsPerLine;
|
const QImage &mask,
|
||||||
auto intsBottomLeft = ints + target.x() + (target.y() + targetHeight - cornerHeight) * imageIntsPerLine;
|
bool right = false,
|
||||||
auto intsBottomRight = ints + target.x() + targetWidth - cornerWidth + (target.y() + targetHeight - cornerHeight) * imageIntsPerLine;
|
bool bottom = false) {
|
||||||
auto maskCorner = [&](uint32 *imageInts, const QImage &mask) {
|
const auto maskWidth = mask.width();
|
||||||
auto maskWidth = mask.width();
|
const auto maskHeight = mask.height();
|
||||||
auto maskHeight = mask.height();
|
if (mask.isNull()
|
||||||
auto maskBytesPerPixel = (mask.depth() >> 3);
|
|| targetWidth < maskWidth
|
||||||
auto maskBytesPerLine = mask.bytesPerLine();
|
|| targetHeight < maskHeight) {
|
||||||
auto maskBytesAdded = maskBytesPerLine - maskWidth * maskBytesPerPixel;
|
return;
|
||||||
auto maskBytes = mask.constBits();
|
}
|
||||||
|
|
||||||
|
const auto maskBytesPerPixel = (mask.depth() >> 3);
|
||||||
|
const auto maskBytesPerLine = mask.bytesPerLine();
|
||||||
|
const auto maskBytesAdded = maskBytesPerLine
|
||||||
|
- maskWidth * maskBytesPerPixel;
|
||||||
Assert(maskBytesAdded >= 0);
|
Assert(maskBytesAdded >= 0);
|
||||||
Assert(mask.depth() == (maskBytesPerPixel << 3));
|
Assert(mask.depth() == (maskBytesPerPixel << 3));
|
||||||
auto imageIntsAdded = imageIntsPerLine - maskWidth * imageIntsPerPixel;
|
const auto imageIntsAdded = imageIntsPerLine
|
||||||
|
- maskWidth * kImageIntsPerPixel;
|
||||||
Assert(imageIntsAdded >= 0);
|
Assert(imageIntsAdded >= 0);
|
||||||
|
auto imageInts = ints + target.x() + target.y() * imageIntsPerLine;
|
||||||
|
if (right) {
|
||||||
|
imageInts += targetWidth - maskWidth;
|
||||||
|
}
|
||||||
|
if (bottom) {
|
||||||
|
imageInts += (targetHeight - maskHeight) * imageIntsPerLine;
|
||||||
|
}
|
||||||
|
auto maskBytes = mask.constBits();
|
||||||
for (auto y = 0; y != maskHeight; ++y) {
|
for (auto y = 0; y != maskHeight; ++y) {
|
||||||
for (auto x = 0; x != maskWidth; ++x) {
|
for (auto x = 0; x != maskWidth; ++x) {
|
||||||
auto opacity = static_cast<anim::ShiftedMultiplier>(*maskBytes) + 1;
|
auto opacity = static_cast<anim::ShiftedMultiplier>(*maskBytes) + 1;
|
||||||
*imageInts = anim::unshifted(anim::shifted(*imageInts) * opacity);
|
*imageInts = anim::unshifted(anim::shifted(*imageInts) * opacity);
|
||||||
maskBytes += maskBytesPerPixel;
|
maskBytes += maskBytesPerPixel;
|
||||||
imageInts += imageIntsPerPixel;
|
imageInts += kImageIntsPerPixel;
|
||||||
}
|
}
|
||||||
maskBytes += maskBytesAdded;
|
maskBytes += maskBytesAdded;
|
||||||
imageInts += imageIntsAdded;
|
imageInts += imageIntsAdded;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (corners & RectPart::TopLeft) maskCorner(intsTopLeft, cornerMasks[0]);
|
|
||||||
if (corners & RectPart::TopRight) maskCorner(intsTopRight, cornerMasks[1]);
|
if (corners & RectPart::TopLeft) maskCorner(cornerMasks[0]);
|
||||||
if (corners & RectPart::BottomLeft) maskCorner(intsBottomLeft, cornerMasks[2]);
|
if (corners & RectPart::TopRight) maskCorner(cornerMasks[1], true);
|
||||||
if (corners & RectPart::BottomRight) maskCorner(intsBottomRight, cornerMasks[3]);
|
if (corners & RectPart::BottomLeft) {
|
||||||
|
maskCorner(cornerMasks[2], false, true);
|
||||||
|
}
|
||||||
|
if (corners & RectPart::BottomRight) {
|
||||||
|
maskCorner(cornerMasks[3], true, true);
|
||||||
|
}
|
||||||
|
|
||||||
return std::move(image);
|
return std::move(image);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue