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