mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-04-01 23:00:58 +00:00
Refactor image transformation interfaces.
This commit is contained in:
parent
a9a6d8a568
commit
3ff17a8789
@ -252,12 +252,13 @@ void ConfirmInviteBox::paintEvent(QPaintEvent *e) {
|
||||
|
||||
if (_photo) {
|
||||
if (const auto image = _photo->image(Data::PhotoSize::Small)) {
|
||||
const auto size = st::confirmInvitePhotoSize;
|
||||
p.drawPixmap(
|
||||
(width() - st::confirmInvitePhotoSize) / 2,
|
||||
(width() - size) / 2,
|
||||
st::confirmInvitePhotoTop,
|
||||
image->pixCircled(
|
||||
st::confirmInvitePhotoSize,
|
||||
st::confirmInvitePhotoSize));
|
||||
image->pix(
|
||||
{ size, size },
|
||||
{ .options = Images::Option::RoundCircle }));
|
||||
}
|
||||
} else if (_photoEmpty) {
|
||||
_photoEmpty->paint(
|
||||
|
@ -321,15 +321,11 @@ bool ServiceCheck::checkRippleStartPosition(QPoint position) const {
|
||||
const auto takeHeight = (width > height)
|
||||
? size
|
||||
: (height * size / width);
|
||||
return Images::prepare(
|
||||
image,
|
||||
takeWidth * cIntRetinaFactor(),
|
||||
takeHeight * cIntRetinaFactor(),
|
||||
Images::Option::Smooth
|
||||
| Images::Option::TransparentBackground
|
||||
| blur,
|
||||
size,
|
||||
size);
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
return Images::Prepare(image, QSize(takeWidth, takeHeight) * ratio, {
|
||||
.options = Images::Option::TransparentBackground | blur,
|
||||
.outer = { size, size },
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] QImage PrepareScaledFromFull(
|
||||
@ -667,7 +663,7 @@ void BackgroundPreviewBox::setScaledFromThumb() {
|
||||
_paper.backgroundColors(),
|
||||
_paper.gradientRotation(),
|
||||
_paper.patternOpacity(),
|
||||
_paper.document() ? Images::Option::Blurred : Images::Option(0));
|
||||
_paper.document() ? Images::Option::Blur : Images::Option());
|
||||
auto blurred = (_paper.document() || _paper.isPattern())
|
||||
? QImage()
|
||||
: PrepareScaledNonPattern(
|
||||
|
@ -183,11 +183,10 @@ void PeerShortInfoCover::paint(QPainter &p) {
|
||||
_widget->size() * style::DevicePixelRatio(),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
image.fill(Qt::black);
|
||||
Images::prepareRound(
|
||||
image,
|
||||
_userpicImage = Images::Round(
|
||||
std::move(image),
|
||||
ImageRoundRadius::Small,
|
||||
RectPart::TopLeft | RectPart::TopRight);
|
||||
_userpicImage = std::move(image);
|
||||
}
|
||||
|
||||
paintCoverImage(p, frame.isNull() ? _userpicImage : frame);
|
||||
@ -229,8 +228,8 @@ void PeerShortInfoCover::paintCoverImage(QPainter &p, const QImage &image) {
|
||||
image,
|
||||
QRect(0, from * factor, roundedWidth * factor, rounded * factor));
|
||||
q.end();
|
||||
Images::prepareRound(
|
||||
_roundedTopImage,
|
||||
_roundedTopImage = Images::Round(
|
||||
std::move(_roundedTopImage),
|
||||
ImageRoundRadius::Small,
|
||||
RectPart::TopLeft | RectPart::TopRight);
|
||||
p.drawImage(
|
||||
@ -244,9 +243,8 @@ void PeerShortInfoCover::paintBars(QPainter &p) {
|
||||
const auto factor = style::DevicePixelRatio();
|
||||
if (_shadowTop.isNull()) {
|
||||
_shadowTop = Images::GenerateShadow(height, kShadowMaxAlpha, 0);
|
||||
_shadowTop = _shadowTop.scaled(QSize(_st.size, height) * factor);
|
||||
Images::prepareRound(
|
||||
_shadowTop,
|
||||
_shadowTop = Images::Round(
|
||||
_shadowTop.scaled(QSize(_st.size, height) * factor),
|
||||
ImageRoundRadius::Small,
|
||||
RectPart::TopLeft | RectPart::TopRight);
|
||||
}
|
||||
@ -771,8 +769,8 @@ int PeerShortInfoBox::fillRoundedTopHeight() {
|
||||
void PeerShortInfoBox::refreshRoundedTopImage(const QColor &color) {
|
||||
_roundedTopColor = color;
|
||||
_roundedTop.fill(color);
|
||||
Images::prepareRound(
|
||||
_roundedTop,
|
||||
_roundedTop = Images::Round(
|
||||
std::move(_roundedTop),
|
||||
ImageRoundRadius::Small,
|
||||
RectPart::TopLeft | RectPart::TopRight);
|
||||
}
|
||||
|
@ -51,19 +51,15 @@ void GenerateImage(
|
||||
bool blurred = false) {
|
||||
using namespace Images;
|
||||
const auto size = st::shortInfoWidth;
|
||||
const auto factor = style::DevicePixelRatio();
|
||||
const auto options = Option::Smooth
|
||||
| Option::RoundedSmall
|
||||
| Option::RoundedTopLeft
|
||||
| Option::RoundedTopRight
|
||||
| (blurred ? Option::Blurred : Option());
|
||||
state->current.photo = Images::prepare(
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
const auto options = Option::RoundSmall
|
||||
| Option::RoundSkipBottomLeft
|
||||
| Option::RoundSkipBottomRight
|
||||
| (blurred ? Option::Blur : Option());
|
||||
state->current.photo = Images::Prepare(
|
||||
std::move(image),
|
||||
size * factor,
|
||||
size * factor,
|
||||
options,
|
||||
size,
|
||||
size);
|
||||
QSize(size, size) * ratio,
|
||||
{ .options = options, .outer = { size, size } });
|
||||
}
|
||||
|
||||
void GenerateImage(
|
||||
|
@ -165,8 +165,12 @@ void Userpic::refreshPhoto() {
|
||||
void Userpic::createCache(Image *image) {
|
||||
const auto size = this->size();
|
||||
const auto real = size * cIntRetinaFactor();
|
||||
auto options = Images::Option::Smooth | Images::Option::Circled;
|
||||
// _useTransparency ? (Images::Option::RoundedLarge | Images::Option::RoundedTopLeft | Images::Option::RoundedTopRight | Images::Option::Smooth) : Images::Option::None;
|
||||
auto options = Images::Option() | Images::Option::RoundCircle;
|
||||
//_useTransparency
|
||||
// ? (Images::Option::RoundLarge
|
||||
// | Images::Option::RoundSkipBottomLeft
|
||||
// | Images::Option::RoundSkipBottomRight)
|
||||
// : Images::Option::None;
|
||||
if (image) {
|
||||
auto width = image->width();
|
||||
auto height = image->height();
|
||||
@ -178,14 +182,16 @@ void Userpic::createCache(Image *image) {
|
||||
width = real;
|
||||
}
|
||||
_userPhoto = image->pixNoCache(
|
||||
width,
|
||||
height,
|
||||
options,
|
||||
size,
|
||||
size);
|
||||
{ width, height },
|
||||
{
|
||||
.options = Images::Option::RoundCircle,
|
||||
.outer = { size, size },
|
||||
});
|
||||
_userPhoto.setDevicePixelRatio(cRetinaFactor());
|
||||
} else {
|
||||
auto filled = QImage(QSize(real, real), QImage::Format_ARGB32_Premultiplied);
|
||||
auto filled = QImage(
|
||||
QSize(real, real),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
filled.setDevicePixelRatio(cRetinaFactor());
|
||||
filled.fill(Qt::transparent);
|
||||
{
|
||||
@ -195,7 +201,10 @@ void Userpic::createCache(Image *image) {
|
||||
_peer->name
|
||||
).paint(p, 0, 0, size, size);
|
||||
}
|
||||
//Images::prepareRound(filled, ImageRoundRadius::Large, RectPart::TopLeft | RectPart::TopRight);
|
||||
//_userPhoto = Images::PixmapFast(Images::Round(
|
||||
// std::move(filled),
|
||||
// ImageRoundRadius::Large,
|
||||
// RectPart::TopLeft | RectPart::TopRight));
|
||||
_userPhoto = Images::PixmapFast(std::move(filled));
|
||||
}
|
||||
|
||||
|
@ -169,12 +169,12 @@ void VideoBubble::prepareFrame() {
|
||||
for (; from != till; from += fromPerLine, to += toPerLine) {
|
||||
memcpy(to, from, lineSize);
|
||||
}
|
||||
Images::prepareRound(
|
||||
_frame,
|
||||
_frame = Images::Round(
|
||||
std::move(_frame),
|
||||
ImageRoundRadius::Large,
|
||||
RectPart::AllCorners,
|
||||
QRect(QPoint(), size));
|
||||
_frame = std::move(_frame).mirrored(true, false);
|
||||
QRect(QPoint(), size)
|
||||
).mirrored(true, false);
|
||||
}
|
||||
|
||||
void VideoBubble::setState(Webrtc::VideoState state) {
|
||||
|
@ -1966,12 +1966,7 @@ void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section,
|
||||
const auto pixmap = !sticker.savedFrame.isNull()
|
||||
? sticker.savedFrame
|
||||
: image
|
||||
? image->pixSingle(
|
||||
w,
|
||||
h,
|
||||
w,
|
||||
h,
|
||||
ImageRoundRadius::None)
|
||||
? image->pixSingle(w, h, { .outer = { w, h } })
|
||||
: QPixmap();
|
||||
if (!pixmap.isNull()) {
|
||||
p.drawPixmapLeft(ppos, width(), pixmap);
|
||||
|
@ -128,9 +128,9 @@ using ItemPreviewImage = HistoryView::ItemPreviewImage;
|
||||
Images::CornersMask(pxRadius)).first->second;
|
||||
}
|
||||
}
|
||||
Images::prepareRound(square, *cache.lastUsed);
|
||||
square = Images::Round(std::move(square), *cache.lastUsed);
|
||||
} else {
|
||||
Images::prepareRound(square, radius);
|
||||
square = Images::Round(std::move(square), radius);
|
||||
}
|
||||
square.setDevicePixelRatio(factor);
|
||||
return square;
|
||||
|
@ -320,7 +320,11 @@ void PeerData::paintUserpic(
|
||||
int y,
|
||||
int size) const {
|
||||
if (const auto userpic = currentUserpic(view)) {
|
||||
p.drawPixmap(x, y, userpic->pixCircled(size, size));
|
||||
const auto circled = Images::Option::RoundCircle;
|
||||
p.drawPixmap(
|
||||
x,
|
||||
y,
|
||||
userpic->pix(size, size, { .options = circled }));
|
||||
} else {
|
||||
ensureEmptyUserpic()->paint(p, x, y, x + size + x, size);
|
||||
}
|
||||
@ -380,10 +384,14 @@ QPixmap PeerData::genUserpic(
|
||||
std::shared_ptr<Data::CloudImageView> &view,
|
||||
int size) const {
|
||||
if (const auto userpic = currentUserpic(view)) {
|
||||
return userpic->pixCircled(size, size);
|
||||
const auto circle = Images::Option::RoundCircle;
|
||||
return userpic->pix(size, size, { .options = circle });
|
||||
}
|
||||
auto result = QImage(QSize(size, size) * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
result.setDevicePixelRatio(cRetinaFactor());
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
auto result = QImage(
|
||||
QSize(size, size) * ratio,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
result.setDevicePixelRatio(ratio);
|
||||
result.fill(Qt::transparent);
|
||||
{
|
||||
Painter p(&result);
|
||||
@ -404,15 +412,13 @@ QImage PeerData::generateUserpicImage(
|
||||
ImageRoundRadius radius) const {
|
||||
if (const auto userpic = currentUserpic(view)) {
|
||||
const auto options = (radius == ImageRoundRadius::Ellipse)
|
||||
? (Images::Option::RoundedAll | Images::Option::Circled)
|
||||
? Images::Option::RoundCircle
|
||||
: (radius == ImageRoundRadius::None)
|
||||
? Images::Options()
|
||||
: (Images::Option::RoundedAll | Images::Option::RoundedSmall);
|
||||
? Images::Option()
|
||||
: Images::Option::RoundSmall;
|
||||
return userpic->pixNoCache(
|
||||
size,
|
||||
size,
|
||||
Images::Option::Smooth | options
|
||||
).toImage();
|
||||
{ size, size },
|
||||
{ .options = options }).toImage();
|
||||
}
|
||||
auto result = QImage(
|
||||
QSize(size, size),
|
||||
|
@ -36,7 +36,7 @@ using Data::kPhotoSizeCount;
|
||||
const Data::CloudFile &file) {
|
||||
return (v::is<WebFileLocation>(file.location.file().data)
|
||||
&& image.format() == QImage::Format_ARGB32)
|
||||
? Images::prepareOpaque(std::move(image))
|
||||
? Images::Opaque(std::move(image))
|
||||
: image;
|
||||
}
|
||||
|
||||
|
@ -41,18 +41,13 @@ void ReplyPreview::prepare(not_null<Image*> image, Images::Options options) {
|
||||
st::msgReplyBarSize.height(),
|
||||
h * st::msgReplyBarSize.height() / w);
|
||||
thumbSize *= cIntRetinaFactor();
|
||||
const auto prepareOptions = Images::Option::Smooth
|
||||
| Images::Option::TransparentBackground
|
||||
| options;
|
||||
options |= Images::Option::TransparentBackground;
|
||||
auto outerSize = st::msgReplyBarSize.height();
|
||||
auto bitmap = image->pixNoCache(
|
||||
thumbSize.width(),
|
||||
thumbSize.height(),
|
||||
prepareOptions,
|
||||
outerSize,
|
||||
outerSize);
|
||||
thumbSize,
|
||||
{ .options = options, .outer = { outerSize, outerSize } });
|
||||
_image = std::make_unique<Image>(bitmap.toImage());
|
||||
_good = ((options & Images::Option::Blurred) == 0);
|
||||
_good = ((options & Images::Option::Blur) == 0);
|
||||
}
|
||||
|
||||
Image *ReplyPreview::image(
|
||||
@ -69,13 +64,13 @@ Image *ReplyPreview::image(
|
||||
}
|
||||
const auto thumbnail = _documentMedia->thumbnail();
|
||||
const auto option = _document->isVideoMessage()
|
||||
? Images::Option::Circled
|
||||
? Images::Option::RoundCircle
|
||||
: Images::Option::None;
|
||||
if (thumbnail) {
|
||||
prepare(thumbnail, option);
|
||||
} else if (!_image) {
|
||||
if (const auto image = _documentMedia->thumbnailInline()) {
|
||||
prepare(image, option | Images::Option::Blurred);
|
||||
prepare(image, option | Images::Option::Blur);
|
||||
}
|
||||
}
|
||||
if (_good || !_document->hasThumbnail()) {
|
||||
@ -102,7 +97,7 @@ Image *ReplyPreview::image(
|
||||
prepare(large, Images::Option(0));
|
||||
} else if (!_image) {
|
||||
if (const auto blurred = _photoMedia->thumbnailInline()) {
|
||||
prepare(blurred, Images::Option::Blurred);
|
||||
prepare(blurred, Images::Option::Blur);
|
||||
}
|
||||
}
|
||||
if (_good) {
|
||||
|
@ -90,9 +90,7 @@ PhotoEditorContent::PhotoEditorContent(
|
||||
|
||||
p.setTransform(_imageMatrix);
|
||||
|
||||
p.drawPixmap(
|
||||
_imageRect,
|
||||
_photo->pix(_imageRect.width(), _imageRect.height()));
|
||||
p.drawPixmap(_imageRect, _photo->pix(_imageRect.size()));
|
||||
}, lifetime());
|
||||
|
||||
setupDragArea();
|
||||
|
@ -90,12 +90,10 @@ QImage EdgeButton::rounded(std::optional<QColor> color) const {
|
||||
result.setDevicePixelRatio(cIntRetinaFactor());
|
||||
result.fill(color.value_or(Qt::white));
|
||||
|
||||
using Option = Images::Option;
|
||||
const auto options = Option::Smooth
|
||||
| Option::RoundedLarge
|
||||
| (_left ? Option::RoundedTopLeft : Option::RoundedTopRight)
|
||||
| (_left ? Option::RoundedBottomLeft : Option::RoundedBottomRight);
|
||||
return Images::prepare(std::move(result), 0, 0, options, 0, 0);
|
||||
const auto parts = RectPart::None
|
||||
| (_left ? RectPart::TopLeft : RectPart::TopRight)
|
||||
| (_left ? RectPart::BottomLeft : RectPart::BottomRight);
|
||||
return Images::Round(std::move(result), ImageRoundRadius::Large, parts);
|
||||
}
|
||||
|
||||
QImage EdgeButton::prepareRippleMask() const {
|
||||
@ -151,10 +149,9 @@ ButtonBar::ButtonBar(
|
||||
result.setDevicePixelRatio(cIntRetinaFactor());
|
||||
result.fill(bg->c);
|
||||
|
||||
const auto options = Images::Option::Smooth
|
||||
| Images::Option::RoundedLarge
|
||||
| Images::Option::RoundedAll;
|
||||
_roundedBg = Images::prepare(std::move(result), 0, 0, options, 0, 0);
|
||||
_roundedBg = Images::Round(
|
||||
std::move(result),
|
||||
ImageRoundRadius::Large);
|
||||
}, lifetime());
|
||||
|
||||
paintRequest(
|
||||
|
@ -59,11 +59,9 @@ ItemSticker::ItemSticker(
|
||||
if (!sticker) {
|
||||
return false;
|
||||
}
|
||||
auto pixmap = sticker->pixNoCache(
|
||||
sticker->width() * cIntRetinaFactor(),
|
||||
sticker->height() * cIntRetinaFactor(),
|
||||
Images::Option::Smooth);
|
||||
pixmap.setDevicePixelRatio(cRetinaFactor());
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
auto pixmap = sticker->pixNoCache(sticker->size() * ratio);
|
||||
pixmap.setDevicePixelRatio(ratio);
|
||||
updatePixmap(std::move(pixmap));
|
||||
return true;
|
||||
};
|
||||
|
@ -342,16 +342,15 @@ void HistoryMessageReply::paint(
|
||||
if (hasPreview) {
|
||||
if (const auto image = replyToMsg->media()->replyPreview()) {
|
||||
auto to = style::rtlrect(x + st::msgReplyBarSkip, y + st::msgReplyPadding.top() + st::msgReplyBarPos.y(), st::msgReplyBarSize.height(), st::msgReplyBarSize.height(), w + 2 * x);
|
||||
auto previewWidth = image->width() / cIntRetinaFactor();
|
||||
auto previewHeight = image->height() / cIntRetinaFactor();
|
||||
auto preview = image->pixSingle(
|
||||
previewWidth,
|
||||
previewHeight,
|
||||
to.width(),
|
||||
to.height(),
|
||||
ImageRoundRadius::Small,
|
||||
RectPart::AllCorners,
|
||||
context.selected() ? &st->msgStickerOverlay() : nullptr);
|
||||
const auto preview = image->pixSingle(
|
||||
image->size() / style::DevicePixelRatio(),
|
||||
{
|
||||
.colored = (context.selected()
|
||||
? &st->msgStickerOverlay()
|
||||
: nullptr),
|
||||
.options = Images::Option::RoundSmall,
|
||||
.outer = to.size(),
|
||||
});
|
||||
p.drawPixmap(to.x(), to.y(), preview);
|
||||
}
|
||||
}
|
||||
|
@ -7139,7 +7139,12 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
|
||||
if (drawMsgText->media() && drawMsgText->media()->hasReplyPreview()) {
|
||||
if (const auto image = drawMsgText->media()->replyPreview()) {
|
||||
auto to = QRect(replyLeft, backy + st::msgReplyPadding.top(), st::msgReplyBarSize.height(), st::msgReplyBarSize.height());
|
||||
p.drawPixmap(to.x(), to.y(), image->pixSingle(image->width() / cIntRetinaFactor(), image->height() / cIntRetinaFactor(), to.width(), to.height(), ImageRoundRadius::Small));
|
||||
p.drawPixmap(to.x(), to.y(), image->pixSingle(
|
||||
image->size() / style::DevicePixelRatio(),
|
||||
{
|
||||
.options = Images::Option::RoundSmall,
|
||||
.outer = to.size(),
|
||||
}));
|
||||
}
|
||||
replyLeft += st::msgReplyBarSize.height() + st::msgReplyBarSkip - st::msgReplyBarSize.width() - st::msgReplyBarPos.x();
|
||||
}
|
||||
|
@ -1144,8 +1144,7 @@ Manager::OverlayImage Manager::validateOverlayShadow(
|
||||
p.end();
|
||||
}
|
||||
|
||||
_overlayShadowScaled = Images::prepareBlur(
|
||||
std::move(_overlayShadowScaled));
|
||||
_overlayShadowScaled = Images::Blur(std::move(_overlayShadowScaled));
|
||||
|
||||
auto q = Painter(result.cache);
|
||||
if (result.cache != &_overlayShadowScaled) {
|
||||
@ -1436,7 +1435,7 @@ QRect Manager::validateShadow(
|
||||
}
|
||||
p.drawRoundedRect(big.translated(0, shift), radius, radius);
|
||||
p.end();
|
||||
_shadowBuffer = Images::prepareBlur(std::move(_shadowBuffer));
|
||||
_shadowBuffer = Images::Blur(std::move(_shadowBuffer));
|
||||
|
||||
auto q = QPainter(&_cacheParts);
|
||||
q.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
|
@ -356,13 +356,18 @@ void Document::draw(
|
||||
const auto inner = QRect(rthumb.x() + (rthumb.width() - innerSize) / 2, rthumb.y() + (rthumb.height() - innerSize) / 2, innerSize, innerSize);
|
||||
const auto radialOpacity = radial ? _animation->radial.opacity() : 1.;
|
||||
if (thumbed) {
|
||||
auto inWebPage = (_parent->media() != this);
|
||||
auto roundRadius = inWebPage ? ImageRoundRadius::Small : ImageRoundRadius::Large;
|
||||
const auto inWebPage = (_parent->media() != this);
|
||||
const auto args = Images::PrepareArgs{
|
||||
.options = (inWebPage
|
||||
? Images::Option::RoundSmall
|
||||
: Images::Option::RoundLarge),
|
||||
.outer = QSize(st.thumbSize, st.thumbSize),
|
||||
};
|
||||
QPixmap thumb;
|
||||
if (const auto normal = _dataMedia->thumbnail()) {
|
||||
thumb = normal->pixSingle(thumbed->_thumbw, 0, st.thumbSize, st.thumbSize, roundRadius);
|
||||
thumb = normal->pixSingle(thumbed->_thumbw, args);
|
||||
} else if (const auto blurred = _dataMedia->thumbnailInline()) {
|
||||
thumb = blurred->pixBlurredSingle(thumbed->_thumbw, 0, st.thumbSize, st.thumbSize, roundRadius);
|
||||
thumb = blurred->pixSingle(thumbed->_thumbw, args.blurred());
|
||||
}
|
||||
p.drawPixmap(rthumb.topLeft(), thumb);
|
||||
if (context.selected()) {
|
||||
@ -1090,32 +1095,27 @@ bool DrawThumbnailAsSongCover(
|
||||
return false;
|
||||
}
|
||||
|
||||
QPixmap cover;
|
||||
|
||||
const auto ow = rect.width();
|
||||
const auto oh = rect.height();
|
||||
const auto r = ImageRoundRadius::Ellipse;
|
||||
const auto c = RectPart::AllCorners;
|
||||
const auto aspectRatio = Qt::KeepAspectRatioByExpanding;
|
||||
|
||||
const auto scaled = [&](not_null<Image*> image) -> std::pair<int, int> {
|
||||
const auto size = image->size().scaled(ow, oh, aspectRatio);
|
||||
return { size.width(), size.height() };
|
||||
auto cover = QPixmap();
|
||||
const auto scaled = [&](not_null<Image*> image) {
|
||||
const auto aspectRatio = Qt::KeepAspectRatioByExpanding;
|
||||
return image->size().scaled(rect.size(), aspectRatio);
|
||||
};
|
||||
const auto args = Images::PrepareArgs{
|
||||
.colored = &colored,
|
||||
.options = Images::Option::RoundCircle,
|
||||
.outer = rect.size(),
|
||||
};
|
||||
|
||||
if (const auto normal = dataMedia->thumbnail()) {
|
||||
const auto &[w, h] = scaled(normal);
|
||||
cover = normal->pixSingle(w, h, ow, oh, r, c, &colored);
|
||||
cover = normal->pixSingle(scaled(normal), args);
|
||||
} else if (const auto blurred = dataMedia->thumbnailInline()) {
|
||||
const auto &[w, h] = scaled(blurred);
|
||||
cover = blurred->pixBlurredSingle(w, h, ow, oh, r, c, &colored);
|
||||
cover = blurred->pixSingle(scaled(blurred), args.blurred());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (selected) {
|
||||
auto selectedCover = Images::prepareColored(
|
||||
p.textPalette().selectOverlay,
|
||||
cover.toImage());
|
||||
auto selectedCover = Images::Colored(
|
||||
cover.toImage(),
|
||||
p.textPalette().selectOverlay);
|
||||
cover = QPixmap::fromImage(
|
||||
std::move(selectedCover),
|
||||
Qt::ColorOnly);
|
||||
|
@ -439,24 +439,28 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
||||
}
|
||||
} else {
|
||||
ensureDataMediaCreated();
|
||||
const auto size = QSize(_thumbw, _thumbh);
|
||||
const auto args = Images::PrepareArgs{
|
||||
.options = Images::RoundOptions(roundRadius, roundCorners),
|
||||
.outer = QSize(usew, painth),
|
||||
};
|
||||
if (const auto good = _dataMedia->goodThumbnail()) {
|
||||
p.drawPixmap(rthumb.topLeft(), good->pixSingle(_thumbw, _thumbh, usew, painth, roundRadius, roundCorners));
|
||||
p.drawPixmap(rthumb.topLeft(), good->pixSingle(size, args));
|
||||
} else {
|
||||
const auto normal = _dataMedia->thumbnail();
|
||||
if (normal) {
|
||||
if (normal->width() >= kUseNonBlurredThreshold
|
||||
|| normal->height() >= kUseNonBlurredThreshold) {
|
||||
p.drawPixmap(rthumb.topLeft(), normal->pixSingle(_thumbw, _thumbh, usew, painth, roundRadius, roundCorners));
|
||||
} else {
|
||||
p.drawPixmap(rthumb.topLeft(), normal->pixBlurredSingle(_thumbw, _thumbh, usew, painth, roundRadius, roundCorners));
|
||||
}
|
||||
const auto blurred = (normal->width() < kUseNonBlurredThreshold)
|
||||
|| (normal->height() < kUseNonBlurredThreshold);
|
||||
p.drawPixmap(
|
||||
rthumb.topLeft(),
|
||||
normal->pixSingle(size, blurred ? args.blurred() : args));
|
||||
} else {
|
||||
_data->loadThumbnail(_realParent->fullId());
|
||||
validateVideoThumbnail();
|
||||
if (_videoThumbnailFrame) {
|
||||
p.drawPixmap(rthumb.topLeft(), _videoThumbnailFrame->pixSingle(_thumbw, _thumbh, usew, painth, roundRadius, roundCorners));
|
||||
p.drawPixmap(rthumb.topLeft(), _videoThumbnailFrame->pixSingle(size, args));
|
||||
} else if (const auto blurred = _dataMedia->thumbnailInline()) {
|
||||
p.drawPixmap(rthumb.topLeft(), blurred->pixBlurredSingle(_thumbw, _thumbh, usew, painth, roundRadius, roundCorners));
|
||||
p.drawPixmap(rthumb.topLeft(), blurred->pixSingle(size, args.blurred()));
|
||||
} else if (!isRound) {
|
||||
const auto roundTop = (roundCorners & RectPart::TopLeft);
|
||||
const auto roundBottom = (roundCorners & RectPart::BottomLeft);
|
||||
@ -1291,13 +1295,15 @@ void Gif::validateGroupedCache(
|
||||
const auto loadLevel = good ? 3 : thumb ? 2 : image ? 1 : 0;
|
||||
const auto width = geometry.width();
|
||||
const auto height = geometry.height();
|
||||
const auto options = Option::Smooth
|
||||
| Option::RoundedLarge
|
||||
| (blur ? Option::Blurred : Option(0))
|
||||
| ((corners & RectPart::TopLeft) ? Option::RoundedTopLeft : Option::None)
|
||||
| ((corners & RectPart::TopRight) ? Option::RoundedTopRight : Option::None)
|
||||
| ((corners & RectPart::BottomLeft) ? Option::RoundedBottomLeft : Option::None)
|
||||
| ((corners & RectPart::BottomRight) ? Option::RoundedBottomRight : Option::None);
|
||||
const auto corner = [&](RectPart part, Option skip) {
|
||||
return !(corners & part) ? skip : Option();
|
||||
};
|
||||
const auto options = Option::RoundLarge
|
||||
| (blur ? Option::Blur : Option(0))
|
||||
| corner(RectPart::TopLeft, Option::RoundSkipTopLeft)
|
||||
| corner(RectPart::TopRight, Option::RoundSkipTopRight)
|
||||
| corner(RectPart::BottomLeft, Option::RoundSkipBottomLeft)
|
||||
| corner(RectPart::BottomRight, Option::RoundSkipBottomRight);
|
||||
const auto key = (uint64(width) << 48)
|
||||
| (uint64(height) << 32)
|
||||
| (uint64(options) << 16)
|
||||
@ -1312,16 +1318,12 @@ void Gif::validateGroupedCache(
|
||||
const auto pixSize = Ui::GetImageScaleSizeForGeometry(
|
||||
{ originalWidth, originalHeight },
|
||||
{ width, height });
|
||||
const auto pixWidth = pixSize.width() * cIntRetinaFactor();
|
||||
const auto pixHeight = pixSize.height() * cIntRetinaFactor();
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
|
||||
*cacheKey = key;
|
||||
*cache = (image ? image : Image::BlankMedia().get())->pixNoCache(
|
||||
pixWidth,
|
||||
pixHeight,
|
||||
options,
|
||||
width,
|
||||
height);
|
||||
pixSize * ratio,
|
||||
{ .options = options, .outer = { width, height } });
|
||||
}
|
||||
|
||||
void Gif::setStatusSize(int newSize) const {
|
||||
|
@ -77,17 +77,15 @@ void LargeEmoji::draw(
|
||||
const auto skip = st::largeEmojiSkip - 2 * st::largeEmojiOutline;
|
||||
const auto size = EmojiImage::Size() / cIntRetinaFactor();
|
||||
for (const auto &image : images) {
|
||||
const auto w = size.width();
|
||||
if (const auto &prepared = image->image) {
|
||||
const auto h = size.height();
|
||||
const auto pixmap = context.selected()
|
||||
? prepared->pixColored(context.st->msgStickerOverlay(), w, h)
|
||||
: prepared->pix(w, h);
|
||||
p.drawPixmap(x, y, pixmap);
|
||||
const auto colored = context.selected()
|
||||
? &context.st->msgStickerOverlay()
|
||||
: nullptr;
|
||||
p.drawPixmap(x, y, prepared->pix(size, { .colored = colored }));
|
||||
} else if (image->load) {
|
||||
image->load();
|
||||
}
|
||||
x += w + skip;
|
||||
x += size.width() + skip;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,8 +194,12 @@ void Location::draw(Painter &p, const PaintContext &context) const {
|
||||
auto rthumb = QRect(paintx, painty, paintw, painth);
|
||||
ensureMediaCreated();
|
||||
if (const auto thumbnail = _media->image()) {
|
||||
const auto &pix = thumbnail->pixSingle(paintw, painth, paintw, painth, roundRadius, roundCorners);
|
||||
p.drawPixmap(rthumb.topLeft(), pix);
|
||||
p.drawPixmap(rthumb.topLeft(), thumbnail->pixSingle(
|
||||
rthumb.size(),
|
||||
{
|
||||
.options = Images::RoundOptions(roundRadius, roundCorners),
|
||||
.outer = rthumb.size(),
|
||||
}));
|
||||
} else {
|
||||
Ui::FillComplexLocationRect(p, st, rthumb, roundRadius, roundCorners);
|
||||
}
|
||||
|
@ -265,21 +265,28 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
|
||||
} else {
|
||||
Ui::FillRoundShadow(p, 0, 0, paintw, painth, sti->msgShadow, sti->msgShadowCorners);
|
||||
}
|
||||
auto inWebPage = (_parent->media() != this);
|
||||
auto roundRadius = inWebPage ? ImageRoundRadius::Small : ImageRoundRadius::Large;
|
||||
auto roundCorners = inWebPage ? RectPart::AllCorners : ((isBubbleTop() ? (RectPart::TopLeft | RectPart::TopRight) : RectPart::None)
|
||||
const auto inWebPage = (_parent->media() != this);
|
||||
const auto roundRadius = inWebPage
|
||||
? ImageRoundRadius::Small
|
||||
: ImageRoundRadius::Large;
|
||||
const auto roundCorners = inWebPage ? RectPart::AllCorners : ((isBubbleTop() ? (RectPart::TopLeft | RectPart::TopRight) : RectPart::None)
|
||||
| ((isRoundedInBubbleBottom() && _caption.isEmpty()) ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None));
|
||||
const auto pix = [&] {
|
||||
const auto size = QSize(_pixw, _pixh);
|
||||
const auto args = Images::PrepareArgs{
|
||||
.options = Images::RoundOptions(roundRadius, roundCorners),
|
||||
.outer = QSize(paintw, painth),
|
||||
};
|
||||
if (const auto large = _dataMedia->image(PhotoSize::Large)) {
|
||||
return large->pixSingle(_pixw, _pixh, paintw, painth, roundRadius, roundCorners);
|
||||
return large->pixSingle(size, args);
|
||||
} else if (const auto thumbnail = _dataMedia->image(
|
||||
PhotoSize::Thumbnail)) {
|
||||
return thumbnail->pixBlurredSingle(_pixw, _pixh, paintw, painth, roundRadius, roundCorners);
|
||||
return thumbnail->pixSingle(size, args.blurred());
|
||||
} else if (const auto small = _dataMedia->image(
|
||||
PhotoSize::Small)) {
|
||||
return small->pixBlurredSingle(_pixw, _pixh, paintw, painth, roundRadius, roundCorners);
|
||||
return small->pixSingle(size, args.blurred());
|
||||
} else if (const auto blurred = _dataMedia->thumbnailInline()) {
|
||||
return blurred->pixBlurredSingle(_pixw, _pixh, paintw, painth, roundRadius, roundCorners);
|
||||
return blurred->pixSingle(size, args.blurred());
|
||||
} else {
|
||||
return QPixmap();
|
||||
}
|
||||
@ -389,16 +396,20 @@ void Photo::paintUserpicFrame(
|
||||
return;
|
||||
}
|
||||
const auto pix = [&] {
|
||||
const auto size = QSize(_pixw, _pixh);
|
||||
const auto args = Images::PrepareArgs{
|
||||
.options = Images::Option::RoundCircle,
|
||||
};
|
||||
if (const auto large = _dataMedia->image(PhotoSize::Large)) {
|
||||
return large->pixCircled(_pixw, _pixh);
|
||||
return large->pix(size, args);
|
||||
} else if (const auto thumbnail = _dataMedia->image(
|
||||
PhotoSize::Thumbnail)) {
|
||||
return thumbnail->pixBlurredCircled(_pixw, _pixh);
|
||||
return thumbnail->pix(size, args.blurred());
|
||||
} else if (const auto small = _dataMedia->image(
|
||||
PhotoSize::Small)) {
|
||||
return small->pixBlurredCircled(_pixw, _pixh);
|
||||
return small->pix(size, args.blurred());
|
||||
} else if (const auto blurred = _dataMedia->thumbnailInline()) {
|
||||
return blurred->pixBlurredCircled(_pixw, _pixh);
|
||||
return blurred->pix(size, args.blurred());
|
||||
} else {
|
||||
return QPixmap();
|
||||
}
|
||||
@ -652,13 +663,15 @@ void Photo::validateGroupedCache(
|
||||
: 0;
|
||||
const auto width = geometry.width();
|
||||
const auto height = geometry.height();
|
||||
const auto options = Option::Smooth
|
||||
| Option::RoundedLarge
|
||||
| (loaded ? Option::None : Option::Blurred)
|
||||
| ((corners & RectPart::TopLeft) ? Option::RoundedTopLeft : Option::None)
|
||||
| ((corners & RectPart::TopRight) ? Option::RoundedTopRight : Option::None)
|
||||
| ((corners & RectPart::BottomLeft) ? Option::RoundedBottomLeft : Option::None)
|
||||
| ((corners & RectPart::BottomRight) ? Option::RoundedBottomRight : Option::None);
|
||||
const auto corner = [&](RectPart part, Option skip) {
|
||||
return !(corners & part) ? skip : Option();
|
||||
};
|
||||
const auto options = Option::RoundLarge
|
||||
| (loaded ? Option() : Option::Blur)
|
||||
| corner(RectPart::TopLeft, Option::RoundSkipTopLeft)
|
||||
| corner(RectPart::TopRight, Option::RoundSkipTopRight)
|
||||
| corner(RectPart::BottomLeft, Option::RoundSkipBottomLeft)
|
||||
| corner(RectPart::BottomRight, Option::RoundSkipBottomRight);
|
||||
const auto key = (uint64(width) << 48)
|
||||
| (uint64(height) << 32)
|
||||
| (uint64(options) << 16)
|
||||
@ -672,8 +685,7 @@ void Photo::validateGroupedCache(
|
||||
const auto pixSize = Ui::GetImageScaleSizeForGeometry(
|
||||
{ originalWidth, originalHeight },
|
||||
{ width, height });
|
||||
const auto pixWidth = pixSize.width() * cIntRetinaFactor();
|
||||
const auto pixHeight = pixSize.height() * cIntRetinaFactor();
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
const auto image = _dataMedia->image(PhotoSize::Large)
|
||||
? _dataMedia->image(PhotoSize::Large)
|
||||
: _dataMedia->image(PhotoSize::Thumbnail)
|
||||
@ -685,7 +697,9 @@ void Photo::validateGroupedCache(
|
||||
: Image::BlankMedia().get();
|
||||
|
||||
*cacheKey = key;
|
||||
*cache = image->pixNoCache(pixWidth, pixHeight, options, width, height);
|
||||
*cache = image->pixNoCache(
|
||||
pixSize * ratio,
|
||||
{ .options = options, .outer = { width, height } });
|
||||
}
|
||||
|
||||
bool Photo::createStreamingObjects() {
|
||||
|
@ -173,7 +173,9 @@ void Sticker::paintLottie(
|
||||
? frame.image
|
||||
: _lastDiceFrame;
|
||||
const auto prepared = (!_lastDiceFrame.isNull() && context.selected())
|
||||
? Images::prepareColored(context.st->msgStickerOverlay()->c, image)
|
||||
? Images::Colored(
|
||||
base::duplicate(image),
|
||||
context.st->msgStickerOverlay()->c)
|
||||
: image;
|
||||
const auto size = prepared.size() / cIntRetinaFactor();
|
||||
p.drawImage(
|
||||
@ -252,27 +254,25 @@ void Sticker::paintPath(
|
||||
QPixmap Sticker::paintedPixmap(const PaintContext &context) const {
|
||||
const auto w = _size.width();
|
||||
const auto h = _size.height();
|
||||
const auto &c = context.st->msgStickerOverlay();
|
||||
const auto colored = context.selected()
|
||||
? &context.st->msgStickerOverlay()
|
||||
: nullptr;
|
||||
const auto good = _dataMedia->goodThumbnail();
|
||||
if (const auto image = _dataMedia->getStickerLarge()) {
|
||||
return context.selected()
|
||||
? image->pixColored(c, w, h)
|
||||
: image->pix(w, h);
|
||||
return image->pix(_size, { .colored = colored });
|
||||
//
|
||||
// Inline thumbnails can't have alpha channel.
|
||||
//
|
||||
//} else if (const auto blurred = _data->thumbnailInline()) {
|
||||
// return context.selected()
|
||||
// ? blurred->pixBlurredColored(c, w, h)
|
||||
// : blurred->pixBlurred(w, h);
|
||||
// return blurred->pix(
|
||||
// _size,
|
||||
// { .colored = colored, .options = Images::Option::Blur });
|
||||
} else if (good) {
|
||||
return context.selected()
|
||||
? good->pixColored(c, w, h)
|
||||
: good->pix(w, h);
|
||||
return good->pix(_size, { .colored = colored });
|
||||
} else if (const auto thumbnail = _dataMedia->thumbnail()) {
|
||||
return context.selected()
|
||||
? thumbnail->pixBlurredColored(c, w, h)
|
||||
: thumbnail->pixBlurred(w, h);
|
||||
return thumbnail->pix(
|
||||
_size,
|
||||
{ .colored = colored, .options = Images::Option::Blur });
|
||||
}
|
||||
return QPixmap();
|
||||
}
|
||||
|
@ -292,8 +292,7 @@ void ThemeDocument::prepareThumbnailFrom(
|
||||
|
||||
const auto isTheme = _data->isTheme();
|
||||
const auto isPattern = _data->isPatternWallPaper();
|
||||
auto options = Images::Option::Smooth
|
||||
| (good >= 0 ? Images::Option(0) : Images::Option::Blurred)
|
||||
auto options = (good >= 0 ? Images::Option(0) : Images::Option::Blur)
|
||||
| (isPattern
|
||||
? Images::Option::TransparentBackground
|
||||
: Images::Option(0));
|
||||
@ -304,20 +303,18 @@ void ThemeDocument::prepareThumbnailFrom(
|
||||
if (!tw || !th) {
|
||||
tw = th = 1;
|
||||
}
|
||||
original = Images::prepare(
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
original = Images::Prepare(
|
||||
std::move(original),
|
||||
_pixw * cIntRetinaFactor(),
|
||||
((_pixw * th) / tw) * cIntRetinaFactor(),
|
||||
options,
|
||||
_pixw,
|
||||
_pixh);
|
||||
QSize(_pixw, (_pixw * th) / tw) * ratio,
|
||||
{ .options = options, .outer = { _pixw, _pixh } });
|
||||
if (isPattern) {
|
||||
original = Ui::PreparePatternImage(
|
||||
std::move(original),
|
||||
_background,
|
||||
_gradientRotation,
|
||||
_patternOpacity);
|
||||
original.setDevicePixelRatio(cRetinaFactor());
|
||||
original.setDevicePixelRatio(ratio);
|
||||
}
|
||||
_thumbnail = Ui::PixmapFromImage(std::move(original));
|
||||
_thumbnailGood = good;
|
||||
|
@ -508,14 +508,19 @@ void WebPage::draw(Painter &p, const PaintContext &context) const {
|
||||
pixh = qRound(pixh * coef);
|
||||
pixw = qRound(pixw * coef);
|
||||
}
|
||||
const auto size = QSize(pixw, pixh);
|
||||
const auto args = Images::PrepareArgs{
|
||||
.options = Images::Option::RoundSmall,
|
||||
.outer = { pw, ph },
|
||||
};
|
||||
if (const auto thumbnail = _photoMedia->image(
|
||||
Data::PhotoSize::Thumbnail)) {
|
||||
pix = thumbnail->pixSingle(pixw, pixh, pw, ph, ImageRoundRadius::Small);
|
||||
pix = thumbnail->pixSingle(size, args);
|
||||
} else if (const auto small = _photoMedia->image(
|
||||
Data::PhotoSize::Small)) {
|
||||
pix = small->pixBlurredSingle(pixw, pixh, pw, ph, ImageRoundRadius::Small);
|
||||
pix = small->pixSingle(size, args.blurred());
|
||||
} else if (const auto blurred = _photoMedia->thumbnailInline()) {
|
||||
pix = blurred->pixBlurredSingle(pixw, pixh, pw, ph, ImageRoundRadius::Small);
|
||||
pix = blurred->pixSingle(size, args.blurred());
|
||||
}
|
||||
p.drawPixmapLeft(padding.left() + paintw - pw, tshift, width(), pix);
|
||||
if (context.selected()) {
|
||||
|
@ -319,13 +319,12 @@ void Gif::validateThumbnail(
|
||||
}
|
||||
_thumbGood = good;
|
||||
_thumb = image->pixNoCache(
|
||||
frame.width() * cIntRetinaFactor(),
|
||||
frame.height() * cIntRetinaFactor(),
|
||||
(Images::Option::Smooth
|
||||
| (good ? Images::Option::None : Images::Option::Blurred)
|
||||
| Images::Option::TransparentBackground),
|
||||
size.width(),
|
||||
size.height());
|
||||
frame * style::DevicePixelRatio(),
|
||||
{
|
||||
.options = (Images::Option::TransparentBackground
|
||||
| (good ? Images::Option() : Images::Option::Blur)),
|
||||
.outer = size,
|
||||
});
|
||||
}
|
||||
|
||||
void Gif::prepareThumbnail(QSize size, QSize frame) const {
|
||||
@ -563,9 +562,7 @@ void Sticker::prepareThumbnail() const {
|
||||
if (const auto sticker = _dataMedia->getStickerSmall()) {
|
||||
if (!_lottie && !_thumbLoaded) {
|
||||
const auto thumbSize = getThumbSize();
|
||||
_thumb = sticker->pix(
|
||||
thumbSize.width(),
|
||||
thumbSize.height());
|
||||
_thumb = sticker->pix(thumbSize);
|
||||
_thumbLoaded = true;
|
||||
}
|
||||
}
|
||||
@ -662,13 +659,12 @@ void Photo::validateThumbnail(
|
||||
}
|
||||
const auto origin = fileOrigin();
|
||||
_thumb = image->pixNoCache(
|
||||
frame.width() * cIntRetinaFactor(),
|
||||
frame.height() * cIntRetinaFactor(),
|
||||
(Images::Option::Smooth
|
||||
| (good ? Images::Option(0) : Images::Option::Blurred)
|
||||
| Images::Option::TransparentBackground),
|
||||
size.width(),
|
||||
size.height());
|
||||
frame * style::DevicePixelRatio(),
|
||||
{
|
||||
.options = (Images::Option::TransparentBackground
|
||||
| (good ? Images::Option() : Images::Option::Blur)),
|
||||
.outer = size,
|
||||
});
|
||||
_thumbGood = good;
|
||||
}
|
||||
|
||||
@ -823,11 +819,11 @@ void Video::prepareThumbnail(QSize size) const {
|
||||
}
|
||||
}
|
||||
_thumb = thumb->pixNoCache(
|
||||
w * cIntRetinaFactor(),
|
||||
h * cIntRetinaFactor(),
|
||||
Images::Option::Smooth | Images::Option::TransparentBackground,
|
||||
width,
|
||||
height);
|
||||
QSize(w, h) * style::DevicePixelRatio(),
|
||||
{
|
||||
.options = Images::Option::TransparentBackground,
|
||||
.outer = size,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1162,11 +1158,11 @@ void Contact::prepareThumbnail(int width, int height) const {
|
||||
}
|
||||
}
|
||||
_thumb = thumb->pixNoCache(
|
||||
w * cIntRetinaFactor(),
|
||||
h * cIntRetinaFactor(),
|
||||
Images::Option::Smooth | Images::Option::TransparentBackground,
|
||||
width,
|
||||
height);
|
||||
QSize(w, h) * style::DevicePixelRatio(),
|
||||
{
|
||||
.options = Images::Option::TransparentBackground,
|
||||
.outer = { width, height },
|
||||
});
|
||||
}
|
||||
|
||||
Article::Article(
|
||||
@ -1320,11 +1316,11 @@ void Article::prepareThumbnail(int width, int height) const {
|
||||
}
|
||||
}
|
||||
_thumb = thumb->pixNoCache(
|
||||
w * cIntRetinaFactor(),
|
||||
h * cIntRetinaFactor(),
|
||||
Images::Option::Smooth | Images::Option::TransparentBackground,
|
||||
width,
|
||||
height);
|
||||
QSize(w, h) * style::DevicePixelRatio(),
|
||||
{
|
||||
.options = Images::Option::TransparentBackground,
|
||||
.outer = { width, height },
|
||||
});
|
||||
}
|
||||
|
||||
Game::Game(not_null<Context*> context, not_null<Result*> result)
|
||||
@ -1539,13 +1535,12 @@ void Game::validateThumbnail(Image *image, QSize size, bool good) const {
|
||||
}
|
||||
_thumbGood = good;
|
||||
_thumb = image->pixNoCache(
|
||||
w * cIntRetinaFactor(),
|
||||
h * cIntRetinaFactor(),
|
||||
(Images::Option::Smooth
|
||||
| (good ? Images::Option::None : Images::Option::Blurred)
|
||||
| Images::Option::TransparentBackground),
|
||||
size.width(),
|
||||
size.height());
|
||||
QSize(w, h) * style::DevicePixelRatio(),
|
||||
{
|
||||
.options = (Images::Option::TransparentBackground
|
||||
| (good ? Images::Option() : Images::Option::Blur)),
|
||||
.outer = size,
|
||||
});
|
||||
}
|
||||
|
||||
bool Game::isRadialAnimation() const {
|
||||
|
@ -79,7 +79,10 @@ QImage PrepareFrameImage(const FrameRequest &request, const QImage &original, bo
|
||||
}
|
||||
}
|
||||
if (needRounding) {
|
||||
Images::prepareRound(cache, request.radius, request.corners);
|
||||
cache = Images::Round(
|
||||
std::move(cache),
|
||||
request.radius,
|
||||
request.corners);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ void Float::prepareShadow() {
|
||||
auto extend = 2 * st::lineWidth;
|
||||
p.drawEllipse(getInnerRect().marginsAdded(QMargins(extend, extend, extend, extend)));
|
||||
}
|
||||
_shadow = Ui::PixmapFromImage(Images::prepareBlur(std::move(shadow)));
|
||||
_shadow = Ui::PixmapFromImage(Images::Blur(std::move(shadow)));
|
||||
}
|
||||
|
||||
QRect Float::getInnerRect() const {
|
||||
|
@ -283,7 +283,10 @@ void ApplyFrameRounding(QImage &storage, const FrameRequest &request) {
|
||||
|| (request.radius == ImageRoundRadius::None)) {
|
||||
return;
|
||||
}
|
||||
Images::prepareRound(storage, request.radius, request.corners);
|
||||
storage = Images::Round(
|
||||
std::move(storage),
|
||||
request.radius,
|
||||
request.corners);
|
||||
}
|
||||
|
||||
QImage PrepareByRequest(
|
||||
|
@ -300,10 +300,7 @@ void GroupThumbs::Thumb::validateImage() {
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation));
|
||||
} else {
|
||||
_full = _image->pixNoCache(
|
||||
pixSize.width() * cIntRetinaFactor(),
|
||||
pixSize.height() * cIntRetinaFactor(),
|
||||
Images::Option::Smooth);
|
||||
_full = _image->pixNoCache(pixSize * style::DevicePixelRatio());
|
||||
}
|
||||
_fullWidth = std::min(
|
||||
wantedPixSize().width(),
|
||||
|
@ -147,9 +147,9 @@ QWidget *PipDelegate::pipParentWidget() {
|
||||
}
|
||||
|
||||
[[nodiscard]] Images::Options VideoThumbOptions(DocumentData *document) {
|
||||
const auto result = Images::Option::Smooth | Images::Option::Blurred;
|
||||
const auto result = Images::Option::Blur;
|
||||
return (document && document->isVideoMessage())
|
||||
? (result | Images::Option::Circled)
|
||||
? (result | Images::Option::RoundCircle)
|
||||
: result;
|
||||
}
|
||||
|
||||
@ -2453,9 +2453,9 @@ void OverlayWidget::displayDocument(
|
||||
if (const auto image = _documentMedia->getStickerLarge()) {
|
||||
setStaticContent(image->original());
|
||||
} else if (const auto thumbnail = _documentMedia->thumbnail()) {
|
||||
setStaticContent(thumbnail->pixBlurred(
|
||||
_document->dimensions.width(),
|
||||
_document->dimensions.height()
|
||||
setStaticContent(thumbnail->pix(
|
||||
_document->dimensions,
|
||||
{ .options = Images::Option::Blur }
|
||||
).toImage());
|
||||
}
|
||||
} else {
|
||||
@ -2712,10 +2712,8 @@ void OverlayWidget::initStreamingThumbnail() {
|
||||
} else if (size.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
const auto w = size.width();
|
||||
const auto h = size.height();
|
||||
const auto options = VideoThumbOptions(_document);
|
||||
const auto goodOptions = (options & ~Images::Option::Blurred);
|
||||
const auto goodOptions = (options & ~Images::Option::Blur);
|
||||
setStaticContent((good
|
||||
? good
|
||||
: thumbnail
|
||||
@ -2723,11 +2721,11 @@ void OverlayWidget::initStreamingThumbnail() {
|
||||
: blurred
|
||||
? blurred
|
||||
: Image::BlankMedia().get())->pixNoCache(
|
||||
w,
|
||||
h,
|
||||
good ? goodOptions : options,
|
||||
w / cIntRetinaFactor(),
|
||||
h / cIntRetinaFactor()
|
||||
size,
|
||||
{
|
||||
.options = good ? goodOptions : options,
|
||||
.outer = size / style::DevicePixelRatio(),
|
||||
}
|
||||
).toImage());
|
||||
}
|
||||
|
||||
@ -3271,10 +3269,8 @@ void OverlayWidget::validatePhotoImage(Image *image, bool blurred) {
|
||||
const auto use = flipSizeByRotation({ _width, _height })
|
||||
* cIntRetinaFactor();
|
||||
setStaticContent(image->pixNoCache(
|
||||
use.width(),
|
||||
use.height(),
|
||||
Images::Option::Smooth
|
||||
| (blurred ? Images::Option::Blurred : Images::Option(0))
|
||||
use,
|
||||
{ .options = (blurred ? Images::Option::Blur : Images::Option()) }
|
||||
).toImage());
|
||||
_blurred = blurred;
|
||||
}
|
||||
|
@ -1660,7 +1660,7 @@ QImage Pip::staticContent() const {
|
||||
? blurred
|
||||
: Image::BlankMedia().get())->original();
|
||||
if (!good) {
|
||||
_preparedCoverStorage = Images::prepareBlur(
|
||||
_preparedCoverStorage = Images::Blur(
|
||||
std::move(_preparedCoverStorage));
|
||||
}
|
||||
}
|
||||
|
@ -175,27 +175,18 @@ QImage Pip::RendererSW::staticContentByRequest(
|
||||
// request,
|
||||
// std::move(_preparedCoverStorage));
|
||||
using Option = Images::Option;
|
||||
const auto options = Option::Smooth
|
||||
| Option::RoundedLarge
|
||||
| ((request.corners & RectPart::TopLeft)
|
||||
? Option::RoundedTopLeft
|
||||
: Option(0))
|
||||
| ((request.corners & RectPart::TopRight)
|
||||
? Option::RoundedTopRight
|
||||
: Option(0))
|
||||
| ((request.corners & RectPart::BottomRight)
|
||||
? Option::RoundedBottomRight
|
||||
: Option(0))
|
||||
| ((request.corners & RectPart::BottomLeft)
|
||||
? Option::RoundedBottomLeft
|
||||
: Option(0));
|
||||
_preparedStaticContent = Images::prepare(
|
||||
const auto corner = [&](RectPart part, Option skip) {
|
||||
return !(request.corners & part) ? skip : Option();
|
||||
};
|
||||
const auto options = Option::RoundLarge
|
||||
| corner(RectPart::TopLeft, Option::RoundSkipTopLeft)
|
||||
| corner(RectPart::TopRight, Option::RoundSkipTopRight)
|
||||
| corner(RectPart::BottomLeft, Option::RoundSkipBottomLeft)
|
||||
| corner(RectPart::BottomRight, Option::RoundSkipBottomRight);
|
||||
_preparedStaticContent = Images::Prepare(
|
||||
image,
|
||||
request.resize.width(),
|
||||
request.resize.height(),
|
||||
options,
|
||||
request.outer.width(),
|
||||
request.outer.height());
|
||||
request.resize,
|
||||
{ .options = options, .outer = request.outer });
|
||||
return _preparedStaticContent;
|
||||
}
|
||||
|
||||
|
@ -358,7 +358,7 @@ void Photo::setPixFrom(not_null<Image*> image) {
|
||||
const auto size = _width * cIntRetinaFactor();
|
||||
auto img = image->original();
|
||||
if (!_goodLoaded) {
|
||||
img = Images::prepareBlur(std::move(img));
|
||||
img = Images::Blur(std::move(img));
|
||||
}
|
||||
if (img.width() == img.height()) {
|
||||
if (img.width() != size) {
|
||||
@ -457,7 +457,7 @@ void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
||||
? good->original()
|
||||
: thumbnail
|
||||
? thumbnail->original()
|
||||
: Images::prepareBlur(blurred->original());
|
||||
: Images::Blur(blurred->original());
|
||||
if (img.width() == img.height()) {
|
||||
if (img.width() != size) {
|
||||
img = img.scaled(size, size, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
|
||||
@ -691,9 +691,11 @@ void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
if (thumbnail || blurred) {
|
||||
const auto thumb = thumbnail
|
||||
? thumbnail->pixCircled(inner.width(), inner.height())
|
||||
: blurred->pixBlurredCircled(inner.width(), inner.height());
|
||||
const auto options = Images::Option::RoundCircle
|
||||
| (blurred ? Images::Option::Blur : Images::Option());
|
||||
const auto thumb = (thumbnail ? thumbnail : blurred)->pix(
|
||||
inner.size(),
|
||||
{ .options = options });
|
||||
p.drawPixmap(inner.topLeft(), thumb);
|
||||
} else if (_data->hasThumbnail()) {
|
||||
PainterHighQualityEnabler hq(p);
|
||||
@ -1101,12 +1103,18 @@ void Document::paint(Painter &p, const QRect &clip, TextSelection selection, con
|
||||
if (thumbnail || blurred) {
|
||||
if (_thumb.isNull() || (thumbnail && !_thumbLoaded)) {
|
||||
_thumbLoaded = (thumbnail != nullptr);
|
||||
auto options = Images::Option::Smooth
|
||||
| (_thumbLoaded
|
||||
? Images::Option::None
|
||||
: Images::Option::Blurred);
|
||||
const auto options = _thumbLoaded
|
||||
? Images::Option()
|
||||
: Images::Option::Blur;
|
||||
const auto image = thumbnail ? thumbnail : blurred;
|
||||
_thumb = image->pixNoCache(_thumbw * cIntRetinaFactor(), 0, options, _st.fileThumbSize, _st.fileThumbSize);
|
||||
_thumb = image->pixNoCache(
|
||||
_thumbw * style::DevicePixelRatio(),
|
||||
{
|
||||
.options = options,
|
||||
.outer = QSize(
|
||||
_st.fileThumbSize,
|
||||
_st.fileThumbSize),
|
||||
});
|
||||
}
|
||||
p.drawPixmap(rthumb.topLeft(), _thumb);
|
||||
} else {
|
||||
@ -1668,20 +1676,26 @@ void Link::validateThumbnail() {
|
||||
if (!_thumbnail.isNull() && !_thumbnailBlurred) {
|
||||
return;
|
||||
}
|
||||
const auto size = QSize(_pixw, _pixh);
|
||||
const auto outer = QSize(st::linksPhotoSize, st::linksPhotoSize);
|
||||
if (_page && _page->photo) {
|
||||
using Data::PhotoSize;
|
||||
ensurePhotoMediaCreated();
|
||||
const auto args = Images::PrepareArgs{
|
||||
.options = Images::Option::RoundSmall,
|
||||
.outer = outer,
|
||||
};
|
||||
if (const auto thumbnail = _photoMedia->image(PhotoSize::Thumbnail)) {
|
||||
_thumbnail = thumbnail->pixSingle(_pixw, _pixh, st::linksPhotoSize, st::linksPhotoSize, ImageRoundRadius::Small);
|
||||
_thumbnail = thumbnail->pixSingle(size, args);
|
||||
_thumbnailBlurred = false;
|
||||
} else if (const auto large = _photoMedia->image(PhotoSize::Large)) {
|
||||
_thumbnail = large->pixSingle(_pixw, _pixh, st::linksPhotoSize, st::linksPhotoSize, ImageRoundRadius::Small);
|
||||
_thumbnail = large->pixSingle(size, args);
|
||||
_thumbnailBlurred = false;
|
||||
} else if (const auto small = _photoMedia->image(PhotoSize::Small)) {
|
||||
_thumbnail = small->pixSingle(_pixw, _pixh, st::linksPhotoSize, st::linksPhotoSize, ImageRoundRadius::Small);
|
||||
_thumbnail = small->pixSingle(size, args);
|
||||
_thumbnailBlurred = false;
|
||||
} else if (const auto blurred = _photoMedia->thumbnailInline()) {
|
||||
_thumbnail = blurred->pixBlurredSingle(_pixw, _pixh, st::linksPhotoSize, st::linksPhotoSize, ImageRoundRadius::Small);
|
||||
_thumbnail = blurred->pixSingle(size, args.blurred());
|
||||
return;
|
||||
} else {
|
||||
return;
|
||||
@ -1690,14 +1704,17 @@ void Link::validateThumbnail() {
|
||||
delegate()->unregisterHeavyItem(this);
|
||||
} else if (_page && _page->document && _page->document->hasThumbnail()) {
|
||||
ensureDocumentMediaCreated();
|
||||
const auto roundRadius = _page->document->isVideoMessage()
|
||||
? ImageRoundRadius::Ellipse
|
||||
: ImageRoundRadius::Small;
|
||||
const auto args = Images::PrepareArgs{
|
||||
.options = (_page->document->isVideoMessage()
|
||||
? Images::Option::RoundCircle
|
||||
: Images::Option::RoundSmall),
|
||||
.outer = outer,
|
||||
};
|
||||
if (const auto thumbnail = _documentMedia->thumbnail()) {
|
||||
_thumbnail = thumbnail->pixSingle(_pixw, _pixh, st::linksPhotoSize, st::linksPhotoSize, roundRadius);
|
||||
_thumbnail = thumbnail->pixSingle(size, args);
|
||||
_thumbnailBlurred = false;
|
||||
} else if (const auto blurred = _documentMedia->thumbnailInline()) {
|
||||
_thumbnail = blurred->pixBlurredSingle(_pixw, _pixh, st::linksPhotoSize, st::linksPhotoSize, roundRadius);
|
||||
_thumbnail = blurred->pixSingle(size, args.blurred());
|
||||
return;
|
||||
} else {
|
||||
return;
|
||||
@ -1930,12 +1947,11 @@ void Gif::validateThumbnail(
|
||||
}
|
||||
_thumbGood = good;
|
||||
_thumb = image->pixNoCache(
|
||||
frame.width() * cIntRetinaFactor(),
|
||||
frame.height() * cIntRetinaFactor(),
|
||||
(Images::Option::Smooth
|
||||
| (good ? Images::Option::None : Images::Option::Blurred)),
|
||||
size.width(),
|
||||
size.height());
|
||||
frame * style::DevicePixelRatio(),
|
||||
{
|
||||
.options = (good ? Images::Option() : Images::Option::Blur),
|
||||
.outer = size,
|
||||
});
|
||||
}
|
||||
|
||||
void Gif::prepareThumbnail(QSize size, QSize frame) {
|
||||
|
@ -239,10 +239,10 @@ QImage Form::prepareThumbnail(
|
||||
not_null<const Image*> image,
|
||||
bool blurred) const {
|
||||
auto result = image->original().scaled(
|
||||
st::paymentsThumbnailSize * cIntRetinaFactor(),
|
||||
st::paymentsThumbnailSize * style::DevicePixelRatio(),
|
||||
Qt::KeepAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
Images::prepareRound(result, ImageRoundRadius::Large);
|
||||
result = Images::Round(std::move(result), ImageRoundRadius::Large);
|
||||
result.setDevicePixelRatio(cRetinaFactor());
|
||||
return result;
|
||||
}
|
||||
|
@ -106,11 +106,8 @@ struct PickerScrubberItem {
|
||||
const auto size = sticker->size()
|
||||
.scaled(kCircleDiameter, kCircleDiameter, Qt::KeepAspectRatio);
|
||||
image = sticker->pixSingle(
|
||||
size.width(),
|
||||
size.height(),
|
||||
kCircleDiameter,
|
||||
kCircleDiameter,
|
||||
ImageRoundRadius::None).toImage();
|
||||
size,
|
||||
{ .outer = { kCircleDiameter, kCircleDiameter } }).toImage();
|
||||
}
|
||||
|
||||
bool isStickerLoaded() const {
|
||||
|
@ -127,8 +127,13 @@ void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRe
|
||||
corners[1] = roundMask.copy(retinaRadius, 0, retinaRadius, retinaRadius);
|
||||
corners[2] = roundMask.copy(0, retinaRadius, retinaRadius, retinaRadius);
|
||||
corners[3] = roundMask.copy(retinaRadius, retinaRadius, retinaRadius, retinaRadius);
|
||||
auto rounded = preview.copy(inner.x() * retina, inner.y() * retina, inner.width() * retina, inner.height() * retina);
|
||||
Images::prepareRound(rounded, corners);
|
||||
auto rounded = Images::Round(
|
||||
preview.copy(
|
||||
inner.x() * retina,
|
||||
inner.y() * retina,
|
||||
inner.width() * retina,
|
||||
inner.height() * retina),
|
||||
corners);
|
||||
rounded.setDevicePixelRatio(cRetinaFactor());
|
||||
preview.fill(st::themePreviewBg->c);
|
||||
|
||||
|
@ -446,8 +446,9 @@ void BackgroundRow::paintEvent(QPaintEvent *e) {
|
||||
if (!backThumb) {
|
||||
p.drawPixmap(0, 0, _background);
|
||||
} else {
|
||||
const auto &pix = backThumb->pixBlurred(
|
||||
st::settingsBackgroundThumb);
|
||||
const auto &pix = backThumb->pix(
|
||||
st::settingsBackgroundThumb,
|
||||
{ .options = Images::Option::Blur });
|
||||
const auto factor = cIntRetinaFactor();
|
||||
p.drawPixmap(
|
||||
0,
|
||||
@ -612,8 +613,8 @@ void BackgroundRow::updateImage() {
|
||||
auto back = (paper.isPattern() || !background.gradientForFill().isNull())
|
||||
? preparePattern()
|
||||
: prepareNormal();
|
||||
Images::prepareRound(back, ImageRoundRadius::Small);
|
||||
_background = Ui::PixmapFromImage(std::move(back));
|
||||
_background = Ui::PixmapFromImage(
|
||||
Images::Round(std::move(back), ImageRoundRadius::Small));
|
||||
_background.setDevicePixelRatio(cRetinaFactor());
|
||||
|
||||
rtlupdate(radialRect());
|
||||
|
@ -724,7 +724,7 @@ void FileLoadTask::process(Args &&args) {
|
||||
&_information->media)) {
|
||||
fullimage = base::take(image->data);
|
||||
if (!Core::IsMimeSticker(filemime)) {
|
||||
fullimage = Images::prepareOpaque(std::move(fullimage));
|
||||
fullimage = Images::Opaque(std::move(fullimage));
|
||||
}
|
||||
isAnimation = image->animated;
|
||||
}
|
||||
@ -743,7 +743,7 @@ void FileLoadTask::process(Args &&args) {
|
||||
const auto mimeType = Core::MimeTypeForData(_content);
|
||||
filemime = mimeType.name();
|
||||
if (!Core::IsMimeSticker(filemime)) {
|
||||
fullimage = Images::prepareOpaque(std::move(fullimage));
|
||||
fullimage = Images::Opaque(std::move(fullimage));
|
||||
}
|
||||
if (filemime == "image/jpeg") {
|
||||
filename = filedialogDefaultName(qsl("photo"), qsl(".jpg"), QString(), true);
|
||||
@ -784,7 +784,7 @@ void FileLoadTask::process(Args &&args) {
|
||||
}
|
||||
filesize = _content.size();
|
||||
}
|
||||
fullimage = Images::prepareOpaque(std::move(fullimage));
|
||||
fullimage = Images::Opaque(std::move(fullimage));
|
||||
}
|
||||
}
|
||||
_result->filesize = (int32)qMin(filesize, qint64(INT_MAX));
|
||||
|
@ -304,7 +304,8 @@ void PrepareDetails(PreparedFile &file, int previewWidth) {
|
||||
} else if (const auto video = std::get_if<Video>(
|
||||
&file.information->media)) {
|
||||
if (ValidVideoForAlbum(*video)) {
|
||||
auto blurred = Images::prepareBlur(Images::prepareOpaque(video->thumbnail));
|
||||
auto blurred = Images::Blur(
|
||||
Images::Opaque(base::duplicate(video->thumbnail)));
|
||||
file.shownDimensions = PrepareShownDimensions(video->thumbnail);
|
||||
file.preview = std::move(blurred).scaledToWidth(
|
||||
previewWidth * cIntRetinaFactor(),
|
||||
@ -333,7 +334,7 @@ void UpdateImageDetails(PreparedFile &file, int previewWidth) {
|
||||
previewWidth,
|
||||
style::ConvertScale(preview.width())
|
||||
) * cIntRetinaFactor();
|
||||
const auto scaled = preview.scaledToWidth(
|
||||
auto scaled = preview.scaledToWidth(
|
||||
toWidth,
|
||||
Qt::SmoothTransformation);
|
||||
if (scaled.isNull()) {
|
||||
@ -345,7 +346,7 @@ void UpdateImageDetails(PreparedFile &file, int previewWidth) {
|
||||
Unexpected("Scaled is null.");
|
||||
}
|
||||
Assert(!scaled.isNull());
|
||||
file.preview = Images::prepareOpaque(scaled);
|
||||
file.preview = Images::Opaque(std::move(scaled));
|
||||
Assert(!file.preview.isNull());
|
||||
file.preview.setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
|
@ -69,19 +69,11 @@ void AbstractSingleFilePreview::prepareThumbFor(
|
||||
if (originalWidth > originalHeight) {
|
||||
thumbWidth = (originalWidth * st.thumbSize) / originalHeight;
|
||||
}
|
||||
auto options = Images::Option::Smooth
|
||||
| Images::Option::RoundedSmall
|
||||
| Images::Option::RoundedTopLeft
|
||||
| Images::Option::RoundedTopRight
|
||||
| Images::Option::RoundedBottomLeft
|
||||
| Images::Option::RoundedBottomRight;
|
||||
data.fileThumb = PixmapFromImage(Images::prepare(
|
||||
const auto options = Images::Option::RoundSmall;
|
||||
data.fileThumb = PixmapFromImage(Images::Prepare(
|
||||
preview,
|
||||
thumbWidth * style::DevicePixelRatio(),
|
||||
0,
|
||||
options,
|
||||
st.thumbSize,
|
||||
st.thumbSize));
|
||||
{ .options = options, .outer = { st.thumbSize, st.thumbSize } }));
|
||||
}
|
||||
|
||||
void AbstractSingleFilePreview::paintEvent(QPaintEvent *e) {
|
||||
|
@ -65,13 +65,11 @@ void AbstractSingleMediaPreview::preparePreview(QImage preview) {
|
||||
maxH = limitH;
|
||||
}
|
||||
}
|
||||
preview = Images::prepare(
|
||||
preview,
|
||||
maxW * style::DevicePixelRatio(),
|
||||
maxH * style::DevicePixelRatio(),
|
||||
Images::Option::Smooth | Images::Option::Blurred,
|
||||
maxW,
|
||||
maxH);
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
preview = Images::Prepare(
|
||||
std::move(preview),
|
||||
QSize(maxW, maxH) * ratio,
|
||||
{ .options = Images::Option::Blur, .outer = { maxW, maxH } });
|
||||
}
|
||||
auto originalWidth = preview.width();
|
||||
auto originalHeight = preview.height();
|
||||
@ -103,7 +101,7 @@ void AbstractSingleMediaPreview::preparePreview(QImage preview) {
|
||||
_previewHeight * style::DevicePixelRatio(),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
preview = Images::prepareOpaque(std::move(preview));
|
||||
preview = Images::Opaque(std::move(preview));
|
||||
_preview = PixmapFromImage(std::move(preview));
|
||||
_preview.setDevicePixelRatio(style::DevicePixelRatio());
|
||||
|
||||
|
@ -44,27 +44,26 @@ AlbumThumbnail::AlbumThumbnail(
|
||||
const auto imageHeight = std::max(
|
||||
previewHeight / style::DevicePixelRatio(),
|
||||
st::minPhotoSize);
|
||||
_photo = PixmapFromImage(Images::prepare(
|
||||
_photo = PixmapFromImage(Images::Prepare(
|
||||
_fullPreview,
|
||||
previewWidth,
|
||||
previewHeight,
|
||||
Option::RoundedLarge | Option::RoundedAll,
|
||||
imageWidth,
|
||||
imageHeight));
|
||||
QSize(previewWidth, previewHeight),
|
||||
{
|
||||
.options = Option::RoundLarge,
|
||||
.outer = { imageWidth, imageHeight },
|
||||
}));
|
||||
|
||||
const auto &st = st::attachPreviewThumbLayout;
|
||||
const auto idealSize = st.thumbSize * style::DevicePixelRatio();
|
||||
const auto fileThumbSize = (previewWidth > previewHeight)
|
||||
? QSize(previewWidth * idealSize / previewHeight, idealSize)
|
||||
: QSize(idealSize, previewHeight * idealSize / previewWidth);
|
||||
_fileThumb = PixmapFromImage(Images::prepare(
|
||||
_fileThumb = PixmapFromImage(Images::Prepare(
|
||||
_fullPreview,
|
||||
fileThumbSize.width(),
|
||||
fileThumbSize.height(),
|
||||
Option::RoundedSmall | Option::RoundedAll,
|
||||
st.thumbSize,
|
||||
st.thumbSize
|
||||
));
|
||||
fileThumbSize,
|
||||
{
|
||||
.options = Option::RoundSmall,
|
||||
.outer = { st.thumbSize, st.thumbSize },
|
||||
}));
|
||||
|
||||
const auto availableFileWidth = st::sendMediaPreviewSize
|
||||
- st.thumbSize
|
||||
@ -138,40 +137,35 @@ void AlbumThumbnail::animateLayoutToInitial() {
|
||||
}
|
||||
|
||||
void AlbumThumbnail::moveToLayout(const GroupMediaLayout &layout) {
|
||||
using Option = Images::Option;
|
||||
|
||||
animateLayoutToInitial();
|
||||
_layout = layout;
|
||||
|
||||
const auto width = _layout.geometry.width();
|
||||
const auto height = _layout.geometry.height();
|
||||
_albumCorners = GetCornersFromSides(_layout.sides);
|
||||
using Option = Images::Option;
|
||||
const auto options = Option::Smooth
|
||||
| Option::RoundedLarge
|
||||
| ((_albumCorners & RectPart::TopLeft)
|
||||
? Option::RoundedTopLeft
|
||||
: Option::None)
|
||||
| ((_albumCorners & RectPart::TopRight)
|
||||
? Option::RoundedTopRight
|
||||
: Option::None)
|
||||
| ((_albumCorners & RectPart::BottomLeft)
|
||||
? Option::RoundedBottomLeft
|
||||
: Option::None)
|
||||
| ((_albumCorners & RectPart::BottomRight)
|
||||
? Option::RoundedBottomRight
|
||||
: Option::None);
|
||||
const auto corner = [&](RectPart part, Option skip) {
|
||||
return !(_albumCorners & part) ? skip : Option();
|
||||
};
|
||||
const auto options = Option::RoundLarge
|
||||
| corner(RectPart::TopLeft, Option::RoundSkipTopLeft)
|
||||
| corner(RectPart::TopRight, Option::RoundSkipTopRight)
|
||||
| corner(RectPart::BottomLeft, Option::RoundSkipBottomLeft)
|
||||
| corner(RectPart::BottomRight, Option::RoundSkipBottomRight);
|
||||
const auto pixSize = GetImageScaleSizeForGeometry(
|
||||
{ _fullPreview.width(), _fullPreview.height() },
|
||||
{ width, height });
|
||||
const auto pixWidth = pixSize.width() * style::DevicePixelRatio();
|
||||
const auto pixHeight = pixSize.height() * style::DevicePixelRatio();
|
||||
|
||||
_albumImage = PixmapFromImage(Images::prepare(
|
||||
_albumImage = PixmapFromImage(Images::Prepare(
|
||||
_fullPreview,
|
||||
pixWidth,
|
||||
pixHeight,
|
||||
options,
|
||||
width,
|
||||
height));
|
||||
QSize(pixWidth, pixHeight),
|
||||
{
|
||||
.options = options,
|
||||
.outer = { width, height },
|
||||
}));
|
||||
}
|
||||
|
||||
int AlbumThumbnail::photoHeight() const {
|
||||
@ -250,8 +244,8 @@ void AlbumThumbnail::prepareCache(QSize size, int shrink) {
|
||||
);
|
||||
drawSimpleFrame(p, to, size);
|
||||
}
|
||||
Images::prepareRound(
|
||||
_albumCache,
|
||||
_albumCache = Images::Round(
|
||||
std::move(_albumCache),
|
||||
ImageRoundRadius::Large,
|
||||
_albumCorners,
|
||||
QRect(QPoint(), size * style::DevicePixelRatio()));
|
||||
|
@ -266,14 +266,15 @@ QPixmap PrepareSongCoverForThumbnail(QImage image, int size) {
|
||||
size,
|
||||
Qt::KeepAspectRatioByExpanding);
|
||||
using Option = Images::Option;
|
||||
return PixmapFromImage(Images::prepare(
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
return PixmapFromImage(Images::Prepare(
|
||||
std::move(image),
|
||||
scaledSize.width() * style::DevicePixelRatio(),
|
||||
scaledSize.height() * style::DevicePixelRatio(),
|
||||
Option::Circled | Option::Colored | Option::Smooth,
|
||||
size,
|
||||
size,
|
||||
&st::songCoverOverlayFg));
|
||||
scaledSize * ratio,
|
||||
{
|
||||
.colored = &st::songCoverOverlayFg,
|
||||
.options = Option::RoundCircle,
|
||||
.outer = { size, size },
|
||||
}));
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
@ -994,7 +994,7 @@ QImage PrepareBlurredBackground(QImage image) {
|
||||
Qt::KeepAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
}
|
||||
return Images::BlurLargeImage(image, kRadius);
|
||||
return Images::BlurLargeImage(std::move(image), kRadius);
|
||||
}
|
||||
|
||||
QImage GenerateDitheredGradient(
|
||||
|
@ -109,8 +109,7 @@ constexpr auto kDisableElement = "disable"_cs;
|
||||
Qt::SmoothTransformation
|
||||
).convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
const auto corners = Images::CornersMask(radius);
|
||||
Images::prepareRound(bubble, corners);
|
||||
p.drawImage(sent, bubble);
|
||||
p.drawImage(sent, Images::Round(std::move(bubble), corners));
|
||||
} else {
|
||||
p.setBrush(theme->palette()->msgOutBg()->c);
|
||||
p.drawRoundedRect(sent, radius, radius);
|
||||
@ -118,8 +117,7 @@ constexpr auto kDisableElement = "disable"_cs;
|
||||
p.setBrush(theme->palette()->msgInBg()->c);
|
||||
p.drawRoundedRect(received, radius, radius);
|
||||
}
|
||||
Images::prepareRound(result, ImageRoundRadius::Large);
|
||||
return result;
|
||||
return Images::Round(std::move(result), ImageRoundRadius::Large);
|
||||
}
|
||||
|
||||
[[nodiscard]] QImage GenerateEmptyPreview() {
|
||||
@ -140,8 +138,7 @@ constexpr auto kDisableElement = "disable"_cs;
|
||||
tr::lng_chat_theme_none(tr::now),
|
||||
style::al_top);
|
||||
}
|
||||
Images::prepareRound(result, ImageRoundRadius::Large);
|
||||
return result;
|
||||
return Images::Round(std::move(result), ImageRoundRadius::Large);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -27,6 +27,18 @@ namespace {
|
||||
return PixKey(0, 0, options);
|
||||
}
|
||||
|
||||
[[nodiscard]] Options OptionsByArgs(const PrepareArgs &args) {
|
||||
return args.options | (args.colored ? Option::Colorize : Option::None);
|
||||
}
|
||||
|
||||
[[nodiscard]] uint64 PixKey(int width, int height, const PrepareArgs &args) {
|
||||
return PixKey(width, height, OptionsByArgs(args));
|
||||
}
|
||||
|
||||
[[nodiscard]] uint64 SinglePixKey(const PrepareArgs &args) {
|
||||
return SinglePixKey(OptionsByArgs(args));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
QByteArray ExpandInlineBytes(const QByteArray &bytes) {
|
||||
@ -330,336 +342,66 @@ QImage Image::original() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
const QPixmap &Image::pix(int w, int h) const {
|
||||
if (w <= 0 || !width() || !height()) {
|
||||
w = width();
|
||||
} else {
|
||||
w *= cIntRetinaFactor();
|
||||
h *= cIntRetinaFactor();
|
||||
}
|
||||
auto options = Option::Smooth | Option::None;
|
||||
auto k = PixKey(w, h, options);
|
||||
auto i = _cache.find(k);
|
||||
if (i == _cache.cend()) {
|
||||
auto p = pixNoCache(w, h, options);
|
||||
p.setDevicePixelRatio(cRetinaFactor());
|
||||
i = _cache.emplace_or_assign(k, p).first;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
|
||||
const QPixmap &Image::pixRounded(
|
||||
const QPixmap &Image::cached(
|
||||
int w,
|
||||
int h,
|
||||
ImageRoundRadius radius,
|
||||
RectParts corners) const {
|
||||
const Images::PrepareArgs &args,
|
||||
bool single) const {
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
if (w <= 0 || !width() || !height()) {
|
||||
w = width();
|
||||
w = width() * ratio;
|
||||
} else if (h <= 0) {
|
||||
h = std::max(int(int64(height()) * w / width()), 1) * ratio;
|
||||
} else {
|
||||
w *= cIntRetinaFactor();
|
||||
h *= cIntRetinaFactor();
|
||||
w *= ratio;
|
||||
h *= ratio;
|
||||
}
|
||||
auto options = Option::Smooth | Option::None;
|
||||
auto cornerOptions = [](RectParts corners) {
|
||||
return (corners & RectPart::TopLeft ? Option::RoundedTopLeft : Option::None)
|
||||
| (corners & RectPart::TopRight ? Option::RoundedTopRight : Option::None)
|
||||
| (corners & RectPart::BottomLeft ? Option::RoundedBottomLeft : Option::None)
|
||||
| (corners & RectPart::BottomRight ? Option::RoundedBottomRight : Option::None);
|
||||
};
|
||||
if (radius == ImageRoundRadius::Large) {
|
||||
options |= Option::RoundedLarge | cornerOptions(corners);
|
||||
} else if (radius == ImageRoundRadius::Small) {
|
||||
options |= Option::RoundedSmall | cornerOptions(corners);
|
||||
} else if (radius == ImageRoundRadius::Ellipse) {
|
||||
options |= Option::Circled | cornerOptions(corners);
|
||||
}
|
||||
auto k = PixKey(w, h, options);
|
||||
auto i = _cache.find(k);
|
||||
if (i == _cache.cend()) {
|
||||
auto p = pixNoCache(w, h, options);
|
||||
p.setDevicePixelRatio(cRetinaFactor());
|
||||
i = _cache.emplace_or_assign(k, p).first;
|
||||
}
|
||||
return i->second;
|
||||
const auto outer = args.outer;
|
||||
const auto size = outer.isEmpty() ? QSize(w, h) : outer * ratio;
|
||||
const auto k = single ? SinglePixKey(args) : PixKey(w, h, args);
|
||||
const auto i = _cache.find(k);
|
||||
return (i != _cache.cend() && i->second.size() == size)
|
||||
? i->second
|
||||
: _cache.emplace_or_assign(k, prepare(w, h, args)).first->second;
|
||||
}
|
||||
|
||||
const QPixmap &Image::pixCircled(int w, int h) const {
|
||||
if (w <= 0 || !width() || !height()) {
|
||||
w = width();
|
||||
} else {
|
||||
w *= cIntRetinaFactor();
|
||||
h *= cIntRetinaFactor();
|
||||
}
|
||||
auto options = Option::Smooth | Option::Circled;
|
||||
auto k = PixKey(w, h, options);
|
||||
auto i = _cache.find(k);
|
||||
if (i == _cache.cend()) {
|
||||
auto p = pixNoCache(w, h, options);
|
||||
p.setDevicePixelRatio(cRetinaFactor());
|
||||
i = _cache.emplace_or_assign(k, p).first;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
|
||||
const QPixmap &Image::pixBlurredCircled(int w, int h) const {
|
||||
if (w <= 0 || !width() || !height()) {
|
||||
w = width();
|
||||
} else {
|
||||
w *= cIntRetinaFactor();
|
||||
h *= cIntRetinaFactor();
|
||||
}
|
||||
auto options = Option::Smooth | Option::Circled | Option::Blurred;
|
||||
auto k = PixKey(w, h, options);
|
||||
auto i = _cache.find(k);
|
||||
if (i == _cache.cend()) {
|
||||
auto p = pixNoCache(w, h, options);
|
||||
p.setDevicePixelRatio(cRetinaFactor());
|
||||
i = _cache.emplace_or_assign(k, p).first;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
|
||||
const QPixmap &Image::pixBlurred(int w, int h) const {
|
||||
if (w <= 0 || !width() || !height()) {
|
||||
w = width() * cIntRetinaFactor();
|
||||
} else {
|
||||
w *= cIntRetinaFactor();
|
||||
h *= cIntRetinaFactor();
|
||||
}
|
||||
auto options = Option::Smooth | Option::Blurred;
|
||||
auto k = PixKey(w, h, options);
|
||||
auto i = _cache.find(k);
|
||||
if (i == _cache.cend()) {
|
||||
auto p = pixNoCache(w, h, options);
|
||||
p.setDevicePixelRatio(cRetinaFactor());
|
||||
i = _cache.emplace_or_assign(k, p).first;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
|
||||
const QPixmap &Image::pixColored(style::color add, int w, int h) const {
|
||||
if (w <= 0 || !width() || !height()) {
|
||||
w = width() * cIntRetinaFactor();
|
||||
} else {
|
||||
w *= cIntRetinaFactor();
|
||||
h *= cIntRetinaFactor();
|
||||
}
|
||||
auto options = Option::Smooth | Option::Colored;
|
||||
auto k = PixKey(w, h, options);
|
||||
auto i = _cache.find(k);
|
||||
if (i == _cache.cend()) {
|
||||
auto p = pixColoredNoCache(add, w, h, true);
|
||||
p.setDevicePixelRatio(cRetinaFactor());
|
||||
i = _cache.emplace_or_assign(k, p).first;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
|
||||
const QPixmap &Image::pixBlurredColored(
|
||||
style::color add,
|
||||
int w,
|
||||
int h) const {
|
||||
if (w <= 0 || !width() || !height()) {
|
||||
w = width() * cIntRetinaFactor();
|
||||
} else {
|
||||
w *= cIntRetinaFactor();
|
||||
h *= cIntRetinaFactor();
|
||||
}
|
||||
auto options = Option::Blurred | Option::Smooth | Option::Colored;
|
||||
auto k = PixKey(w, h, options);
|
||||
auto i = _cache.find(k);
|
||||
if (i == _cache.cend()) {
|
||||
auto p = pixBlurredColoredNoCache(add, w, h);
|
||||
p.setDevicePixelRatio(cRetinaFactor());
|
||||
i = _cache.emplace_or_assign(k, p).first;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
|
||||
const QPixmap &Image::pixSingle(
|
||||
int w,
|
||||
int h,
|
||||
int outerw,
|
||||
int outerh,
|
||||
ImageRoundRadius radius,
|
||||
RectParts corners,
|
||||
const style::color *colored) const {
|
||||
if (w <= 0 || !width() || !height()) {
|
||||
w = width() * cIntRetinaFactor();
|
||||
} else {
|
||||
w *= cIntRetinaFactor();
|
||||
h *= cIntRetinaFactor();
|
||||
}
|
||||
|
||||
auto options = Option::Smooth | Option::None;
|
||||
auto cornerOptions = [](RectParts corners) {
|
||||
return (corners & RectPart::TopLeft ? Option::RoundedTopLeft : Option::None)
|
||||
| (corners & RectPart::TopRight ? Option::RoundedTopRight : Option::None)
|
||||
| (corners & RectPart::BottomLeft ? Option::RoundedBottomLeft : Option::None)
|
||||
| (corners & RectPart::BottomRight ? Option::RoundedBottomRight : Option::None);
|
||||
};
|
||||
if (radius == ImageRoundRadius::Large) {
|
||||
options |= Option::RoundedLarge | cornerOptions(corners);
|
||||
} else if (radius == ImageRoundRadius::Small) {
|
||||
options |= Option::RoundedSmall | cornerOptions(corners);
|
||||
} else if (radius == ImageRoundRadius::Ellipse) {
|
||||
options |= Option::Circled | cornerOptions(corners);
|
||||
}
|
||||
if (colored) {
|
||||
options |= Option::Colored;
|
||||
}
|
||||
|
||||
auto k = SinglePixKey(options);
|
||||
auto i = _cache.find(k);
|
||||
if (i == _cache.cend() || i->second.width() != (outerw * cIntRetinaFactor()) || i->second.height() != (outerh * cIntRetinaFactor())) {
|
||||
auto p = pixNoCache(w, h, options, outerw, outerh, colored);
|
||||
p.setDevicePixelRatio(cRetinaFactor());
|
||||
i = _cache.emplace_or_assign(k, p).first;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
|
||||
const QPixmap &Image::pixBlurredSingle(
|
||||
int w,
|
||||
int h,
|
||||
int outerw,
|
||||
int outerh,
|
||||
ImageRoundRadius radius,
|
||||
RectParts corners,
|
||||
const style::color *colored) const {
|
||||
if (w <= 0 || !width() || !height()) {
|
||||
w = width() * cIntRetinaFactor();
|
||||
} else {
|
||||
w *= cIntRetinaFactor();
|
||||
h *= cIntRetinaFactor();
|
||||
}
|
||||
|
||||
auto options = Option::Smooth | Option::Blurred;
|
||||
auto cornerOptions = [](RectParts corners) {
|
||||
return (corners & RectPart::TopLeft ? Option::RoundedTopLeft : Option::None)
|
||||
| (corners & RectPart::TopRight ? Option::RoundedTopRight : Option::None)
|
||||
| (corners & RectPart::BottomLeft ? Option::RoundedBottomLeft : Option::None)
|
||||
| (corners & RectPart::BottomRight ? Option::RoundedBottomRight : Option::None);
|
||||
};
|
||||
if (radius == ImageRoundRadius::Large) {
|
||||
options |= Option::RoundedLarge | cornerOptions(corners);
|
||||
} else if (radius == ImageRoundRadius::Small) {
|
||||
options |= Option::RoundedSmall | cornerOptions(corners);
|
||||
} else if (radius == ImageRoundRadius::Ellipse) {
|
||||
options |= Option::Circled | cornerOptions(corners);
|
||||
}
|
||||
if (colored) {
|
||||
options |= Option::Colored;
|
||||
}
|
||||
|
||||
auto k = SinglePixKey(options);
|
||||
auto i = _cache.find(k);
|
||||
if (i == _cache.cend() || i->second.width() != (outerw * cIntRetinaFactor()) || i->second.height() != (outerh * cIntRetinaFactor())) {
|
||||
auto p = pixNoCache(w, h, options, outerw, outerh, colored);
|
||||
p.setDevicePixelRatio(cRetinaFactor());
|
||||
i = _cache.emplace_or_assign(k, p).first;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
|
||||
QPixmap Image::pixNoCache(
|
||||
int w,
|
||||
int h,
|
||||
Options options,
|
||||
int outerw,
|
||||
int outerh,
|
||||
const style::color *colored) const {
|
||||
QPixmap Image::prepare(int w, int h, const Images::PrepareArgs &args) const {
|
||||
if (_data.isNull()) {
|
||||
if (h <= 0 && height() > 0) {
|
||||
h = qRound(width() * w / float64(height()));
|
||||
}
|
||||
return Empty()->pixNoCache(w, h, options, outerw, outerh);
|
||||
return Empty()->prepare(w, h, args);
|
||||
}
|
||||
|
||||
if (isNull() && outerw > 0 && outerh > 0) {
|
||||
outerw *= cIntRetinaFactor();
|
||||
outerh *= cIntRetinaFactor();
|
||||
|
||||
QImage result(outerw, outerh, QImage::Format_ARGB32_Premultiplied);
|
||||
result.setDevicePixelRatio(style::DevicePixelRatio());
|
||||
|
||||
{
|
||||
QPainter p(&result);
|
||||
if (w < outerw) {
|
||||
p.fillRect(0, 0, (outerw - w) / 2, result.height(), st::imageBg);
|
||||
p.fillRect(((outerw - w) / 2) + w, 0, result.width() - (((outerw - w) / 2) + w), result.height(), st::imageBg);
|
||||
}
|
||||
if (h < outerh) {
|
||||
p.fillRect(qMax(0, (outerw - w) / 2), 0, qMin(result.width(), w), (outerh - h) / 2, st::imageBg);
|
||||
p.fillRect(qMax(0, (outerw - w) / 2), ((outerh - h) / 2) + h, qMin(result.width(), w), result.height() - (((outerh - h) / 2) + h), st::imageBg);
|
||||
}
|
||||
p.fillRect(qMax(0, (outerw - w) / 2), qMax(0, (outerh - h) / 2), qMin(result.width(), w), qMin(result.height(), h), st::imageBgTransparent);
|
||||
}
|
||||
|
||||
auto corners = [](Options options) {
|
||||
return ((options & Option::RoundedTopLeft) ? RectPart::TopLeft : RectPart::None)
|
||||
| ((options & Option::RoundedTopRight) ? RectPart::TopRight : RectPart::None)
|
||||
| ((options & Option::RoundedBottomLeft) ? RectPart::BottomLeft : RectPart::None)
|
||||
| ((options & Option::RoundedBottomRight) ? RectPart::BottomRight : RectPart::None);
|
||||
};
|
||||
if (options & Option::Circled) {
|
||||
prepareCircle(result);
|
||||
} else if (options & Option::RoundedLarge) {
|
||||
prepareRound(result, ImageRoundRadius::Large, corners(options));
|
||||
} else if (options & Option::RoundedSmall) {
|
||||
prepareRound(result, ImageRoundRadius::Small, corners(options));
|
||||
}
|
||||
if (options & Option::Colored) {
|
||||
Assert(colored != nullptr);
|
||||
result = prepareColored(*colored, std::move(result));
|
||||
}
|
||||
return Ui::PixmapFromImage(std::move(result));
|
||||
auto outer = args.outer;
|
||||
if (!isNull() || outer.isEmpty()) {
|
||||
return Ui::PixmapFromImage(Prepare(_data, w, h, args));
|
||||
}
|
||||
|
||||
return Ui::PixmapFromImage(
|
||||
prepare(_data, w, h, options, outerw, outerh, colored));
|
||||
}
|
||||
|
||||
QPixmap Image::pixColoredNoCache(
|
||||
style::color add,
|
||||
int w,
|
||||
int h,
|
||||
bool smooth) const {
|
||||
if (_data.isNull()) {
|
||||
return Empty()->pix();
|
||||
}
|
||||
|
||||
auto img = _data;
|
||||
if (w <= 0 || !width() || !height() || (w == width() && (h <= 0 || h == height()))) {
|
||||
return Ui::PixmapFromImage(prepareColored(add, std::move(img)));
|
||||
}
|
||||
const auto transformation = smooth
|
||||
? Qt::SmoothTransformation
|
||||
: Qt::FastTransformation;
|
||||
if (h <= 0) {
|
||||
return Ui::PixmapFromImage(
|
||||
prepareColored(add, img.scaledToWidth(w, transformation)));
|
||||
}
|
||||
return Ui::PixmapFromImage(
|
||||
prepareColored(
|
||||
add,
|
||||
img.scaled(w, h, Qt::IgnoreAspectRatio, transformation)));
|
||||
}
|
||||
|
||||
QPixmap Image::pixBlurredColoredNoCache(
|
||||
style::color add,
|
||||
int w,
|
||||
int h) const {
|
||||
if (_data.isNull()) {
|
||||
return Empty()->pix();
|
||||
}
|
||||
|
||||
auto img = prepareBlur(_data);
|
||||
if (h <= 0) {
|
||||
img = img.scaledToWidth(w, Qt::SmoothTransformation);
|
||||
} else {
|
||||
img = img.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
|
||||
return Ui::PixmapFromImage(prepareColored(add, img));
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
const auto outerw = outer.width() * ratio;
|
||||
const auto outerh = outer.height() * ratio;
|
||||
|
||||
auto result = QImage(
|
||||
QSize(outerw, outerh),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
result.setDevicePixelRatio(ratio);
|
||||
|
||||
auto p = QPainter(&result);
|
||||
if (w < outerw) {
|
||||
p.fillRect(0, 0, (outerw - w) / 2, result.height(), Qt::black);
|
||||
p.fillRect(((outerw - w) / 2) + w, 0, result.width() - (((outerw - w) / 2) + w), result.height(), Qt::black);
|
||||
}
|
||||
if (h < outerh) {
|
||||
p.fillRect(qMax(0, (outerw - w) / 2), 0, qMin(result.width(), w), (outerh - h) / 2, Qt::black);
|
||||
p.fillRect(qMax(0, (outerw - w) / 2), ((outerh - h) / 2) + h, qMin(result.width(), w), result.height() - (((outerh - h) / 2) + h), Qt::black);
|
||||
}
|
||||
p.fillRect(qMax(0, (outerw - w) / 2), qMax(0, (outerh - h) / 2), qMin(result.width(), w), qMin(result.height(), h), Qt::white);
|
||||
p.end();
|
||||
|
||||
result = Round(std::move(result), args.options);
|
||||
if (args.colored) {
|
||||
result = Colored(std::move(result), *args.colored);
|
||||
}
|
||||
return Ui::PixmapFromImage(std::move(result));
|
||||
}
|
||||
|
@ -44,54 +44,68 @@ public:
|
||||
|
||||
[[nodiscard]] QImage original() const;
|
||||
|
||||
[[nodiscard]] const QPixmap &pix(int w = 0, int h = 0) const;
|
||||
[[nodiscard]] const QPixmap &pixRounded(
|
||||
int w = 0,
|
||||
int h = 0,
|
||||
ImageRoundRadius radius = ImageRoundRadius::None,
|
||||
RectParts corners = RectPart::AllCorners) const;
|
||||
[[nodiscard]] const QPixmap &pixBlurred(int w = 0, int h = 0) const;
|
||||
[[nodiscard]] const QPixmap &pixColored(style::color add, int w = 0, int h = 0) const;
|
||||
[[nodiscard]] const QPixmap &pixBlurredColored(
|
||||
style::color add,
|
||||
int w = 0,
|
||||
int h = 0) const;
|
||||
[[nodiscard]] const QPixmap &pix(
|
||||
QSize size,
|
||||
const Images::PrepareArgs &args = {}) const {
|
||||
return cached(size.width(), size.height(), args, false);
|
||||
}
|
||||
[[nodiscard]] const QPixmap &pix(
|
||||
int w,
|
||||
int h,
|
||||
const Images::PrepareArgs &args = {}) const {
|
||||
return cached(w, h, args, false);
|
||||
}
|
||||
[[nodiscard]] const QPixmap &pix(
|
||||
int w = 0,
|
||||
const Images::PrepareArgs &args = {}) const {
|
||||
return cached(w, 0, args, false);
|
||||
}
|
||||
|
||||
[[nodiscard]] const QPixmap &pixSingle(
|
||||
int w,
|
||||
int h,
|
||||
int outerw,
|
||||
int outerh,
|
||||
ImageRoundRadius radius,
|
||||
RectParts corners = RectPart::AllCorners,
|
||||
const style::color *colored = nullptr) const;
|
||||
[[nodiscard]] const QPixmap &pixBlurredSingle(
|
||||
int w,
|
||||
int h,
|
||||
int outerw,
|
||||
int outerh,
|
||||
ImageRoundRadius radius,
|
||||
RectParts corners = RectPart::AllCorners,
|
||||
const style::color *colored = nullptr) const;
|
||||
[[nodiscard]] const QPixmap &pixCircled(int w = 0, int h = 0) const;
|
||||
[[nodiscard]] const QPixmap &pixBlurredCircled(int w = 0, int h = 0) const;
|
||||
QSize size,
|
||||
const Images::PrepareArgs &args = {}) const {
|
||||
return cached(size.width(), size.height(), args, true);
|
||||
}
|
||||
[[nodiscard]] const QPixmap &pixSingle(
|
||||
int w,
|
||||
int h,
|
||||
const Images::PrepareArgs &args = {}) const {
|
||||
return cached(w, h, args, true);
|
||||
}
|
||||
[[nodiscard]] const QPixmap &pixSingle(
|
||||
int w = 0,
|
||||
const Images::PrepareArgs &args = {}) const {
|
||||
return cached(w, 0, args, true);
|
||||
}
|
||||
|
||||
[[nodiscard]] QPixmap pixNoCache(
|
||||
int w = 0,
|
||||
int h = 0,
|
||||
Images::Options options = 0,
|
||||
int outerw = -1,
|
||||
int outerh = -1,
|
||||
const style::color *colored = nullptr) const;
|
||||
[[nodiscard]] QPixmap pixColoredNoCache(
|
||||
style::color add,
|
||||
int w = 0,
|
||||
int h = 0,
|
||||
bool smooth = false) const;
|
||||
[[nodiscard]] QPixmap pixBlurredColoredNoCache(
|
||||
style::color add,
|
||||
int w,
|
||||
int h = 0) const;
|
||||
QSize size,
|
||||
const Images::PrepareArgs &args = {}) const {
|
||||
return prepare(size.width(), size.height(), args);
|
||||
}
|
||||
[[nodiscard]] QPixmap pixNoCache(
|
||||
int w,
|
||||
int h,
|
||||
const Images::PrepareArgs &args = {}) const {
|
||||
return prepare(w, h, args);
|
||||
}
|
||||
[[nodiscard]] QPixmap pixNoCache(
|
||||
int w = 0,
|
||||
const Images::PrepareArgs &args = {}) const {
|
||||
return prepare(w, 0, args);
|
||||
}
|
||||
|
||||
private:
|
||||
[[nodiscard]] QPixmap prepare(
|
||||
int w,
|
||||
int h,
|
||||
const Images::PrepareArgs &args) const;
|
||||
[[nodiscard]] const QPixmap &cached(
|
||||
int w,
|
||||
int h,
|
||||
const Images::PrepareArgs &args,
|
||||
bool single) const;
|
||||
|
||||
const QImage _data;
|
||||
mutable base::flat_map<uint64, QPixmap> _cache;
|
||||
|
||||
|
@ -696,8 +696,7 @@ void UserpicButton::setImage(QImage &&image) {
|
||||
size * cIntRetinaFactor(),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
Images::prepareCircle(small);
|
||||
_userpic = Ui::PixmapFromImage(std::move(small));
|
||||
_userpic = Ui::PixmapFromImage(Images::Circle(std::move(small)));
|
||||
_userpic.setDevicePixelRatio(cRetinaFactor());
|
||||
_userpicCustom = _userpicHasImage = true;
|
||||
_result = std::move(image);
|
||||
|
@ -169,8 +169,8 @@ void BackgroundSelector::updateThumbnail() {
|
||||
int s = (pix.width() > pix.height()) ? pix.height() : pix.width();
|
||||
p.drawImage(QRect(0, 0, size, size), pix, QRect(sx, sy, s, s));
|
||||
}
|
||||
Images::prepareRound(back, ImageRoundRadius::Small);
|
||||
_thumbnail = Ui::PixmapFromImage(std::move(back));
|
||||
_thumbnail = Ui::PixmapFromImage(
|
||||
Images::Round(std::move(back), ImageRoundRadius::Small));
|
||||
_thumbnail.setDevicePixelRatio(cRetinaFactor());
|
||||
update();
|
||||
}
|
||||
|
@ -968,7 +968,7 @@ void Generator::paintUserpic(int x, int y, Row::Type type, int index, QString le
|
||||
p.setPen(st::historyPeerUserpicFg[_palette]);
|
||||
p.drawText(QRect(0, 0, st::dialogsPhotoSize, st::dialogsPhotoSize), letters, QTextOption(style::al_center));
|
||||
}
|
||||
Images::prepareCircle(image);
|
||||
image = Images::Circle(std::move(image));
|
||||
_p->drawImage(rtl() ? (_rect.width() - x - st::dialogsPhotoSize) : x, y, image);
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,9 @@ void CloudListCheck::validateBackgroundCache(int width) {
|
||||
0,
|
||||
imageWidth,
|
||||
_backgroundFull.height());
|
||||
Images::prepareRound(_backgroundCache, ImageRoundRadius::Large);
|
||||
_backgroundCache = Images::Round(
|
||||
std::move(_backgroundCache),
|
||||
ImageRoundRadius::Large);
|
||||
_backgroundCache.setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
|
||||
|
@ -258,6 +258,7 @@ void MediaPreviewWidget::setupLottie() {
|
||||
}
|
||||
|
||||
QPixmap MediaPreviewWidget::currentImage() const {
|
||||
const auto blur = Images::PrepareArgs{ .options = Images::Option::Blur };
|
||||
if (_document) {
|
||||
if (const auto sticker = _document->sticker()) {
|
||||
if (_cacheStatus != CacheLoaded) {
|
||||
@ -268,13 +269,13 @@ QPixmap MediaPreviewWidget::currentImage() const {
|
||||
return QPixmap();
|
||||
} else if (const auto image = _documentMedia->getStickerLarge()) {
|
||||
QSize s = currentDimensions();
|
||||
_cache = image->pix(s.width(), s.height());
|
||||
_cache = image->pix(s);
|
||||
_cacheStatus = CacheLoaded;
|
||||
} else if (_cacheStatus != CacheThumbLoaded
|
||||
&& _document->hasThumbnail()
|
||||
&& _documentMedia->thumbnail()) {
|
||||
QSize s = currentDimensions();
|
||||
_cache = _documentMedia->thumbnail()->pixBlurred(s.width(), s.height());
|
||||
_cache = _documentMedia->thumbnail()->pix(s, blur);
|
||||
_cacheStatus = CacheThumbLoaded;
|
||||
}
|
||||
}
|
||||
@ -293,10 +294,10 @@ QPixmap MediaPreviewWidget::currentImage() const {
|
||||
QSize s = currentDimensions();
|
||||
const auto thumbnail = _documentMedia->thumbnail();
|
||||
if (thumbnail) {
|
||||
_cache = thumbnail->pixBlurred(s.width(), s.height());
|
||||
_cache = thumbnail->pix(s, blur);
|
||||
_cacheStatus = CacheThumbLoaded;
|
||||
} else if (const auto blurred = _documentMedia->thumbnailInline()) {
|
||||
_cache = blurred->pixBlurred(s.width(), s.height());
|
||||
_cache = blurred->pix(s, blur);
|
||||
_cacheStatus = CacheThumbLoaded;
|
||||
}
|
||||
}
|
||||
@ -305,7 +306,7 @@ QPixmap MediaPreviewWidget::currentImage() const {
|
||||
if (_cacheStatus != CacheLoaded) {
|
||||
if (_photoMedia->loaded()) {
|
||||
QSize s = currentDimensions();
|
||||
_cache = _photoMedia->image(Data::PhotoSize::Large)->pix(s.width(), s.height());
|
||||
_cache = _photoMedia->image(Data::PhotoSize::Large)->pix(s);
|
||||
_cacheStatus = CacheLoaded;
|
||||
} else {
|
||||
_photo->load(_origin);
|
||||
@ -313,14 +314,14 @@ QPixmap MediaPreviewWidget::currentImage() const {
|
||||
QSize s = currentDimensions();
|
||||
if (const auto thumbnail = _photoMedia->image(
|
||||
Data::PhotoSize::Thumbnail)) {
|
||||
_cache = thumbnail->pixBlurred(s.width(), s.height());
|
||||
_cache = thumbnail->pix(s, blur);
|
||||
_cacheStatus = CacheThumbLoaded;
|
||||
} else if (const auto small = _photoMedia->image(
|
||||
Data::PhotoSize::Small)) {
|
||||
_cache = small->pixBlurred(s.width(), s.height());
|
||||
_cache = small->pix(s, blur);
|
||||
_cacheStatus = CacheThumbLoaded;
|
||||
} else if (const auto blurred = _photoMedia->thumbnailInline()) {
|
||||
_cache = blurred->pixBlurred(s.width(), s.height());
|
||||
_cache = blurred->pix(s, blur);
|
||||
_cacheStatus = CacheThumbLoaded;
|
||||
} else {
|
||||
_photoMedia->wanted(Data::PhotoSize::Small, _origin);
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 17fbf3dec42290ed0c00c2458be82f6e8bdd47e9
|
||||
Subproject commit f20776cf6541342c88e540b96e843cadb27016e0
|
@ -1 +1 @@
|
||||
Subproject commit 04886885929086dea6fa80c038efc6f372d6996a
|
||||
Subproject commit 87e62b7737a68e9293e29f6467ca145a781ac9e6
|
Loading…
Reference in New Issue
Block a user