Seek done in video player in MediaView. Some memory leaks fixed.

Using pixmapFromImageInPlace() instead of QPixmap::fromImage().
This commit is contained in:
John Preston 2016-07-13 20:34:57 +03:00
parent fc716af002
commit cb0c99acc8
53 changed files with 419 additions and 274 deletions

View File

@ -2064,7 +2064,7 @@ namespace {
cors[3] = rect.copy(r * 2, r * 2, r, r + (shadow ? s : 0));
if (index != SmallMaskCorners && index != LargeMaskCorners) {
for (int i = 0; i < 4; ++i) {
::corners[index].p[i] = new QPixmap(QPixmap::fromImage(cors[i], Qt::ColorOnly));
::corners[index].p[i] = new QPixmap(pixmapFromImageInPlace(std_::move(cors[i])));
::corners[index].p[i]->setDevicePixelRatio(cRetinaFactor());
}
}
@ -2101,12 +2101,12 @@ namespace {
}
QImage mask[4];
prepareCorners(LargeMaskCorners, st::msgRadius, st::white, 0, mask);
prepareCorners(LargeMaskCorners, st::msgRadius, st::white, nullptr, mask);
for (int i = 0; i < 4; ++i) {
::cornersMaskLarge[i] = new QImage(mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied));
::cornersMaskLarge[i]->setDevicePixelRatio(cRetinaFactor());
}
prepareCorners(SmallMaskCorners, st::buttonRadius, st::white, 0, mask);
prepareCorners(SmallMaskCorners, st::buttonRadius, st::white, nullptr, mask);
for (int i = 0; i < 4; ++i) {
::cornersMaskSmall[i] = new QImage(mask[i].convertToFormat(QImage::Format_ARGB32_Premultiplied));
::cornersMaskSmall[i]->setDevicePixelRatio(cRetinaFactor());
@ -2267,7 +2267,7 @@ namespace {
p.setCompositionMode(m);
emojiDraw(p, emoji, st::emojiPadding * cIntRetinaFactor(), (fontHeight * cIntRetinaFactor() - ESize) / 2);
}
i = map->insert(emojiKey(emoji), QPixmap::fromImage(img, Qt::ColorOnly));
i = map->insert(emojiKey(emoji), App::pixmapFromImageInPlace(std_::move(img)));
}
return i.value();
}
@ -2603,13 +2603,13 @@ namespace {
if (i == cornersMap.cend()) {
QImage images[4];
switch (radius) {
case ImageRoundRadius::Small: prepareCorners(SmallMaskCorners, st::buttonRadius, bg, 0, images); break;
case ImageRoundRadius::Large: prepareCorners(LargeMaskCorners, st::msgRadius, bg, 0, images); break;
case ImageRoundRadius::Small: prepareCorners(SmallMaskCorners, st::buttonRadius, bg, nullptr, images); break;
case ImageRoundRadius::Large: prepareCorners(LargeMaskCorners, st::msgRadius, bg, nullptr, images); break;
}
CornersPixmaps pixmaps;
for (int j = 0; j < 4; ++j) {
pixmaps.p[j] = new QPixmap(QPixmap::fromImage(images[j], Qt::ColorOnly));
pixmaps.p[j] = new QPixmap(pixmapFromImageInPlace(std_::move(images[j])));
pixmaps.p[j]->setDevicePixelRatio(cRetinaFactor());
}
i = cornersMap.insert(colorKey, pixmaps);
@ -2620,46 +2620,51 @@ namespace {
void initBackground(int32 id, const QImage &p, bool nowrite) {
if (Local::readBackground()) return;
QImage img(p);
bool remove = false;
if (p.isNull()) {
if (id == DefaultChatBackground) {
img.load(st::msgBG);
} else {
img.load(st::msgBG0);
if (cRetina()) {
img = img.scaledToWidth(img.width() * 2, Qt::SmoothTransformation);
} else if (cScale() != dbisOne) {
img = img.scaledToWidth(convertScale(img.width()), Qt::SmoothTransformation);
}
id = 0;
}
remove = true;
}
if (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_ARGB32_Premultiplied && img.format() != QImage::Format_RGB32) {
img = img.convertToFormat(QImage::Format_RGB32);
}
img.setDevicePixelRatio(cRetinaFactor());
if (!nowrite) {
Local::writeBackground(id, remove ? QImage() : img);
}
delete cChatBackground();
cSetChatBackground(new QPixmap(QPixmap::fromImage(img, Qt::ColorOnly)));
cSetChatBackgroundId(id);
if (App::main()) App::main()->clearCachedBackground();
uint64 components[3] = { 0 }, componentsScroll[3] = { 0 }, componentsPoint[3] = { 0 };
int w = img.width(), h = img.height(), size = w * h;
const uchar *pix = img.constBits();
if (pix) {
for (int32 i = 0, l = size * 4; i < l; i += 4) {
components[2] += pix[i + 0];
components[1] += pix[i + 1];
components[0] += pix[i + 2];
int size = 0;
{
QImage img(p);
bool remove = false;
if (p.isNull()) {
if (id == DefaultChatBackground) {
img.load(st::msgBG);
} else {
img.load(st::msgBG0);
if (cRetina()) {
img = img.scaledToWidth(img.width() * 2, Qt::SmoothTransformation);
} else if (cScale() != dbisOne) {
img = img.scaledToWidth(convertScale(img.width()), Qt::SmoothTransformation);
}
id = 0;
}
remove = true;
}
if (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_ARGB32_Premultiplied && img.format() != QImage::Format_RGB32) {
img = img.convertToFormat(QImage::Format_RGB32);
}
img.setDevicePixelRatio(cRetinaFactor());
if (!nowrite) {
Local::writeBackground(id, remove ? QImage() : img);
}
int w = img.width(), h = img.height();
size = w * h;
const uchar *pix = img.constBits();
if (pix) {
for (int32 i = 0, l = size * 4; i < l; i += 4) {
components[2] += pix[i + 0];
components[1] += pix[i + 1];
components[0] += pix[i + 2];
}
}
delete cChatBackground();
cSetChatBackground(new QPixmap(pixmapFromImageInPlace(std_::move(img))));
cSetChatBackgroundId(id);
if (App::main()) App::main()->clearCachedBackground();
}
if (size) {
for (int32 i = 0; i < 3; ++i) components[i] /= size;
@ -2677,41 +2682,43 @@ namespace {
uint64 max = qMax(1ULL, components[maxtomin[0]]), mid = qMax(1ULL, components[maxtomin[1]]), min = qMax(1ULL, components[maxtomin[2]]);
QImage dog = App::sprite().toImage().copy(st::msgDogImg.rect());
QImage::Format f = dog.format();
if (f != QImage::Format_ARGB32 && f != QImage::Format_ARGB32_Premultiplied) {
dog = dog.convertToFormat(QImage::Format_ARGB32_Premultiplied);
}
uchar *dogBits = dog.bits();
if (max != min) {
float64 coef = float64(mid - min) / float64(max - min);
for (int i = 0, s = dog.width() * dog.height() * 4; i < s; i += 4) {
int dogmaxtomin[3] = { i, i + 1, i + 2 };
if (dogBits[dogmaxtomin[0]] < dogBits[dogmaxtomin[1]]) {
qSwap(dogmaxtomin[0], dogmaxtomin[1]);
}
if (dogBits[dogmaxtomin[1]] < dogBits[dogmaxtomin[2]]) {
qSwap(dogmaxtomin[1], dogmaxtomin[2]);
{
QImage dog = App::sprite().toImage().copy(st::msgDogImg.rect());
QImage::Format f = dog.format();
if (f != QImage::Format_ARGB32 && f != QImage::Format_ARGB32_Premultiplied) {
dog = dog.convertToFormat(QImage::Format_ARGB32_Premultiplied);
}
uchar *dogBits = dog.bits();
if (max != min) {
float64 coef = float64(mid - min) / float64(max - min);
for (int i = 0, s = dog.width() * dog.height() * 4; i < s; i += 4) {
int dogmaxtomin[3] = { i, i + 1, i + 2 };
if (dogBits[dogmaxtomin[0]] < dogBits[dogmaxtomin[1]]) {
qSwap(dogmaxtomin[0], dogmaxtomin[1]);
}
if (dogBits[dogmaxtomin[1]] < dogBits[dogmaxtomin[2]]) {
qSwap(dogmaxtomin[1], dogmaxtomin[2]);
if (dogBits[dogmaxtomin[0]] < dogBits[dogmaxtomin[1]]) {
qSwap(dogmaxtomin[0], dogmaxtomin[1]);
}
}
uchar result[3];
result[maxtomin[0]] = dogBits[dogmaxtomin[0]];
result[maxtomin[2]] = dogBits[dogmaxtomin[2]];
result[maxtomin[1]] = uchar(qRound(result[maxtomin[2]] + (result[maxtomin[0]] - result[maxtomin[2]]) * coef));
dogBits[i] = result[2];
dogBits[i + 1] = result[1];
dogBits[i + 2] = result[0];
}
} else {
for (int i = 0, s = dog.width() * dog.height() * 4; i < s; i += 4) {
uchar b = dogBits[i], g = dogBits[i + 1], r = dogBits[i + 2];
dogBits[i] = dogBits[i + 1] = dogBits[i + 2] = (r + r + b + g + g + g) / 6;
}
uchar result[3];
result[maxtomin[0]] = dogBits[dogmaxtomin[0]];
result[maxtomin[2]] = dogBits[dogmaxtomin[2]];
result[maxtomin[1]] = uchar(qRound(result[maxtomin[2]] + (result[maxtomin[0]] - result[maxtomin[2]]) * coef));
dogBits[i] = result[2];
dogBits[i + 1] = result[1];
dogBits[i + 2] = result[0];
}
} else {
for (int i = 0, s = dog.width() * dog.height() * 4; i < s; i += 4) {
uchar b = dogBits[i], g = dogBits[i + 1], r = dogBits[i + 2];
dogBits[i] = dogBits[i + 1] = dogBits[i + 2] = (r + r + b + g + g + g) / 6;
}
delete cChatDogImage();
cSetChatDogImage(new QPixmap(pixmapFromImageInPlace(std_::move(dog))));
}
delete cChatDogImage();
cSetChatDogImage(new QPixmap(QPixmap::fromImage(dog)));
memcpy(componentsScroll, components, sizeof(components));
memcpy(componentsPoint, components, sizeof(components));
@ -2768,6 +2775,10 @@ namespace {
uchar bsel = snap(qRound(((1. - alphaSel) * b + addSel) / alphaSel), 0, 0xFF);
_msgServiceSelectBg = style::color(r, g, b, qRound(alphaSel * 0xFF));
for (int i = 0; i < 4; ++i) {
delete ::corners[StickerCorners].p[i]; ::corners[StickerCorners].p[i] = nullptr;
delete ::corners[StickerSelectedCorners].p[i]; ::corners[StickerSelectedCorners].p[i] = nullptr;
}
prepareCorners(StickerCorners, st::dateRadius, _msgServiceBg);
prepareCorners(StickerSelectedCorners, st::dateRadius, _msgServiceSelectBg);

View File

@ -1014,11 +1014,11 @@ void AppClass::uploadProfilePhoto(const QImage &tosend, const PeerId &peerId) {
PreparedPhotoThumbs photoThumbs;
QVector<MTPPhotoSize> photoSizes;
QPixmap thumb = QPixmap::fromImage(tosend.scaled(160, 160, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly);
QPixmap thumb = App::pixmapFromImageInPlace(tosend.scaled(160, 160, Qt::KeepAspectRatio, Qt::SmoothTransformation));
photoThumbs.insert('a', thumb);
photoSizes.push_back(MTP_photoSize(MTP_string("a"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0)));
QPixmap medium = QPixmap::fromImage(tosend.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly);
QPixmap medium = App::pixmapFromImageInPlace(tosend.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation));
photoThumbs.insert('b', medium);
photoSizes.push_back(MTP_photoSize(MTP_string("b"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));

View File

@ -595,7 +595,7 @@ void GroupInfoBox::onPhoto() {
void GroupInfoBox::onPhotoReady(const QImage &img) {
_photoBig = img;
_photoSmall = QPixmap::fromImage(img.scaled(st::newGroupPhotoSize * cIntRetinaFactor(), st::newGroupPhotoSize * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly);
_photoSmall = App::pixmapFromImageInPlace(img.scaled(st::newGroupPhotoSize * cIntRetinaFactor(), st::newGroupPhotoSize * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
_photoSmall.setDevicePixelRatio(cRetinaFactor());
}

View File

@ -61,7 +61,7 @@ void PhotoCropBox::init(const QImage &img, PeerData *peer) {
}
int32 s = st::boxWideWidth - st::boxPhotoPadding.left() - st::boxPhotoPadding.right();
_thumb = QPixmap::fromImage(img.scaled(s, s, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly);
_thumb = App::pixmapFromImageInPlace(img.scaled(s, s, Qt::KeepAspectRatio, Qt::SmoothTransformation));
_thumbw = _thumb.width();
_thumbh = _thumb.height();
if (_thumbw > _thumbh) {

View File

@ -110,7 +110,7 @@ PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxW
}
_thumbx = (width() - _thumbw) / 2;
_thumb = QPixmap::fromImage(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(), _thumbh * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly);
_thumb = App::pixmapFromImageInPlace(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(), _thumbh * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
_thumb.setDevicePixelRatio(cRetinaFactor());
} else {
if (_file->thumb.isNull()) {
@ -483,7 +483,7 @@ EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth)
}
_thumbx = (width() - _thumbw) / 2;
_thumb = QPixmap::fromImage(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(), _thumbh * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly);
_thumb = App::pixmapFromImageInPlace(_thumb.toImage().scaled(_thumbw * cIntRetinaFactor(), _thumbh * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
_thumb.setDevicePixelRatio(cRetinaFactor());
}

View File

@ -24,6 +24,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include <openssl/crypto.h>
#include <openssl/sha.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/engine.h>
#include <openssl/conf.h>
#include <openssl/ssl.h>
extern "C" {
#include <libavcodec/avcodec.h>
@ -288,10 +293,19 @@ namespace ThirdParty {
}
void finish() {
av_lockmgr_register(0);
av_lockmgr_register(nullptr);
CRYPTO_cleanup_all_ex_data();
FIPS_mode_set(0);
ENGINE_cleanup();
CONF_modules_unload(1);
ERR_remove_state(0);
ERR_free_strings();
ERR_remove_thread_state(nullptr);
EVP_cleanup();
delete[] _sslLocks;
_sslLocks = 0;
_sslLocks = nullptr;
Platform::ThirdParty::finish();
}

View File

@ -5857,7 +5857,7 @@ HistoryWebPage::~HistoryWebPage() {
}
namespace {
LocationManager manager;
LocationManager *locationManager = nullptr;
}
void LocationManager::init() {
@ -5869,13 +5869,16 @@ void LocationManager::init() {
connect(manager, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)), this, SLOT(onFailed(QNetworkReply*)));
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*)));
if (black) delete black;
if (black) {
delete black->v();
delete black;
}
QImage b(cIntRetinaFactor(), cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
{
QPainter p(&b);
p.fillRect(QRect(0, 0, cIntRetinaFactor(), cIntRetinaFactor()), st::white->b);
}
QPixmap p = QPixmap::fromImage(b, Qt::ColorOnly);
QPixmap p = App::pixmapFromImageInPlace(std_::move(b));
p.setDevicePixelRatio(cRetinaFactor());
black = new ImagePtr(p, "PNG");
}
@ -5887,26 +5890,36 @@ void LocationManager::reinit() {
void LocationManager::deinit() {
if (manager) {
delete manager;
manager = 0;
manager = nullptr;
}
if (black) {
delete black->v();
delete black;
black = 0;
black = nullptr;
}
dataLoadings.clear();
imageLoadings.clear();
}
void initImageLinkManager() {
manager.init();
if (!locationManager) {
locationManager = new LocationManager();
locationManager->init();
}
}
void reinitImageLinkManager() {
manager.reinit();
if (locationManager) {
locationManager->reinit();
}
}
void deinitImageLinkManager() {
manager.deinit();
if (locationManager) {
locationManager->deinit();
delete locationManager;
locationManager = nullptr;
}
}
void LocationManager::getData(LocationData *data) {
@ -6046,7 +6059,9 @@ void LocationData::load() {
if (loading) return;
loading = true;
manager.getData(this);
if (locationManager) {
locationManager->getData(this);
}
}
HistoryLocation::HistoryLocation(HistoryItem *parent, const LocationCoords &coords, const QString &title, const QString &description) : HistoryMedia(parent)

View File

@ -2445,8 +2445,6 @@ struct LocationData;
class LocationManager : public QObject {
Q_OBJECT
public:
LocationManager() : manager(0), black(0) {
}
void init();
void reinit();
void deinit();
@ -2464,10 +2462,10 @@ public slots:
private:
void failed(LocationData *data);
QNetworkAccessManager *manager;
QNetworkAccessManager *manager = nullptr;
QMap<QNetworkReply*, LocationData*> dataLoadings, imageLoadings;
QMap<LocationData*, int32> serverRedirects;
ImagePtr *black;
ImagePtr *black = nullptr;
};
class HistoryLocation : public HistoryMedia {

View File

@ -53,7 +53,7 @@ FieldAutocomplete::FieldAutocomplete(QWidget *parent) : TWidget(parent)
_inner->setGeometry(rect());
_scroll->setGeometry(rect());
_scroll->setWidget(_inner);
_scroll->setOwnedWidget(_inner);
_scroll->show();
_inner->show();
@ -946,4 +946,7 @@ void FieldAutocompleteInner::onPreview() {
}
}
FieldAutocompleteInner::~FieldAutocompleteInner() {
}
} // namespace internal

View File

@ -37,7 +37,6 @@ class FieldAutocomplete final : public TWidget {
Q_OBJECT
public:
FieldAutocomplete(QWidget *parent);
void fastHide();
@ -79,7 +78,6 @@ public:
~FieldAutocomplete();
signals:
void mentionChosen(UserData *user, FieldAutocomplete::ChooseMethod method) const;
void hashtagChosen(QString hashtag, FieldAutocomplete::ChooseMethod method) const;
void botCommandChosen(QString command, FieldAutocomplete::ChooseMethod method) const;
@ -88,14 +86,12 @@ signals:
void moderateKeyActivate(int key, bool *outHandled) const;
public slots:
void hideStart();
void hideFinish();
void showStart();
private:
void paintEvent(QPaintEvent *e) override;
void updateFiltered(bool resetScroll = false);
@ -146,7 +142,6 @@ class FieldAutocompleteInner final : public TWidget {
Q_OBJECT
public:
FieldAutocompleteInner(FieldAutocomplete *parent, MentionRows *mrows, HashtagRows *hrows, BotCommandRows *brows, StickerPack *srows);
void clearSel(bool hidden = false);
@ -155,8 +150,9 @@ public:
void setRecentInlineBotsInRows(int32 bots);
signals:
~FieldAutocompleteInner();
signals:
void mentionChosen(UserData *user, FieldAutocomplete::ChooseMethod method) const;
void hashtagChosen(QString hashtag, FieldAutocomplete::ChooseMethod method) const;
void botCommandChosen(QString command, FieldAutocomplete::ChooseMethod method) const;
@ -164,13 +160,11 @@ signals:
void mustScrollTo(int scrollToTop, int scrollToBottom);
public slots:
void onParentGeometryChanged();
void onUpdateSelected(bool force = false);
void onPreview();
private:
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
@ -199,6 +193,7 @@ private:
bool _previewShown;
QTimer _previewTimer;
};
} // namespace internal

View File

@ -2143,7 +2143,7 @@ int HistoryInner::itemTop(const HistoryItem *item) const { // -1 if should not b
}
void HistoryInner::notifyIsBotChanged() {
BotInfo *newinfo = (_history && _history->peer->isUser()) ? _history->peer->asUser()->botInfo : nullptr;
BotInfo *newinfo = (_history && _history->peer->isUser()) ? _history->peer->asUser()->botInfo.get() : nullptr;
if ((!newinfo && !_botAbout) || (newinfo && _botAbout && _botAbout->info == newinfo)) {
return;
}

View File

@ -242,7 +242,7 @@ void IntroSignup::onCheckRequest() {
void IntroSignup::onPhotoReady(const QImage &img) {
_photoBig = img;
_photoSmall = QPixmap::fromImage(img.scaled(st::introPhotoSize * cIntRetinaFactor(), st::introPhotoSize * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly);
_photoSmall = App::pixmapFromImageInPlace(img.scaled(st::introPhotoSize * cIntRetinaFactor(), st::introPhotoSize * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
_photoSmall.setDevicePixelRatio(cRetinaFactor());
}

View File

@ -312,7 +312,7 @@ void FileLoadTask::process() {
if (!cover.isNull()) { // cover to thumb
int32 cw = cover.width(), ch = cover.height();
if (cw < 20 * ch && ch < 20 * cw) {
QPixmap full = (cw > 90 || ch > 90) ? QPixmap::fromImage(cover.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(cover, Qt::ColorOnly);
QPixmap full = (cw > 90 || ch > 90) ? App::pixmapFromImageInPlace(cover.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : App::pixmapFromImageInPlace(std_::move(cover));
{
QByteArray thumbFormat = "JPG";
int32 thumbQuality = 87;
@ -339,7 +339,7 @@ void FileLoadTask::process() {
attributes.push_back(animatedAttribute);
gif = true;
QPixmap full = (cw > 90 || ch > 90) ? QPixmap::fromImage(cover.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(cover, Qt::ColorOnly);
QPixmap full = (cw > 90 || ch > 90) ? App::pixmapFromImageInPlace(cover.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : App::pixmapFromImageInPlace(std_::move(cover));
{
QByteArray thumbFormat = "JPG";
int32 thumbQuality = 87;
@ -369,15 +369,15 @@ void FileLoadTask::process() {
if (animated) {
attributes.push_back(MTP_documentAttributeAnimated());
} else if (_type != PrepareDocument) {
QPixmap thumb = (w > 100 || h > 100) ? QPixmap::fromImage(fullimage.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(fullimage);
QPixmap thumb = (w > 100 || h > 100) ? App::pixmapFromImageInPlace(fullimage.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
photoThumbs.insert('s', thumb);
photoSizes.push_back(MTP_photoSize(MTP_string("s"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0)));
QPixmap medium = (w > 320 || h > 320) ? QPixmap::fromImage(fullimage.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(fullimage);
QPixmap medium = (w > 320 || h > 320) ? App::pixmapFromImageInPlace(fullimage.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
photoThumbs.insert('m', medium);
photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));
QPixmap full = (w > 1280 || h > 1280) ? QPixmap::fromImage(fullimage.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(fullimage);
QPixmap full = (w > 1280 || h > 1280) ? App::pixmapFromImageInPlace(fullimage.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
photoThumbs.insert('y', full);
photoSizes.push_back(MTP_photoSize(MTP_string("y"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0)));
@ -397,7 +397,7 @@ void FileLoadTask::process() {
thumbname = qsl("thumb.webp");
}
QPixmap full = (w > 90 || h > 90) ? QPixmap::fromImage(fullimage.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(fullimage, Qt::ColorOnly);
QPixmap full = (w > 90 || h > 90) ? App::pixmapFromImageInPlace(fullimage.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage, Qt::ColorOnly);
{
QBuffer buffer(&thumbdata);

View File

@ -2643,7 +2643,7 @@ namespace Local {
case StorageFileWebp: guessFormat = "WEBP"; break;
default: guessFormat = QByteArray(); break;
}
pixmap = QPixmap::fromImage(App::readImage(data, &guessFormat, false), Qt::ColorOnly);
pixmap = App::pixmapFromImageInPlace(App::readImage(data, &guessFormat, false));
if (!pixmap.isNull()) {
format = guessFormat;
}
@ -2910,7 +2910,7 @@ namespace Local {
struct Result {
Result(StorageFileType type, const QByteArray &data) : image(type, data) {
QByteArray guessFormat;
pixmap = QPixmap::fromImage(App::readImage(data, &guessFormat, false), Qt::ColorOnly);
pixmap = App::pixmapFromImageInPlace(App::readImage(data, &guessFormat, false));
if (!pixmap.isNull()) {
format = guessFormat;
}

View File

@ -1019,13 +1019,13 @@ void MainWidget::onCacheBackground() {
}
_cachedX = 0;
_cachedY = 0;
_cachedBackground = QPixmap::fromImage(result);
_cachedBackground = App::pixmapFromImageInPlace(std_::move(result));
} else {
QRect to, from;
backgroundParams(_willCacheFor, to, from);
_cachedX = to.x();
_cachedY = to.y();
_cachedBackground = QPixmap::fromImage(bg.toImage().copy(from).scaled(to.width() * cIntRetinaFactor(), to.height() * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
_cachedBackground = App::pixmapFromImageInPlace(bg.toImage().copy(from).scaled(to.width() * cIntRetinaFactor(), to.height() * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
_cachedBackground.setDevicePixelRatio(cRetinaFactor());
}
_cachedFor = _willCacheFor;

View File

@ -174,7 +174,7 @@ void NotifyWindow::updateNotifyDisplay() {
history->peer->loadUserpic(true, true);
history->peer->paintUserpicLeft(p, st::notifyPhotoSize, st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), width());
} else {
static QPixmap icon = QPixmap::fromImage(App::wnd()->iconLarge().scaled(st::notifyPhotoSize, st::notifyPhotoSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly);
static QPixmap icon = App::pixmapFromImageInPlace(App::wnd()->iconLarge().scaled(st::notifyPhotoSize, st::notifyPhotoSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
p.drawPixmap(st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), icon);
}
@ -234,7 +234,7 @@ void NotifyWindow::updateNotifyDisplay() {
}
}
pm = QPixmap::fromImage(img, Qt::ColorOnly);
pm = App::pixmapFromImageInPlace(std_::move(img));
update();
}
@ -246,7 +246,7 @@ void NotifyWindow::updatePeerPhoto() {
p.drawPixmap(st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), peerPhoto->pix(st::notifyPhotoSize));
}
peerPhoto = ImagePtr();
pm = QPixmap::fromImage(img, Qt::ColorOnly);
pm = App::pixmapFromImageInPlace(std_::move(img));
update();
}
}
@ -1882,7 +1882,7 @@ QImage MainWindow::iconWithCounter(int size, int count, style::color bg, bool sm
placeSmallCounter(img, size, count, bg, QPoint(), st::counterColor);
} else {
QPainter p(&img);
p.drawPixmap(size / 2, size / 2, QPixmap::fromImage(iconWithCounter(-size / 2, count, bg, false), Qt::ColorOnly));
p.drawPixmap(size / 2, size / 2, App::pixmapFromImageInPlace(iconWithCounter(-size / 2, count, bg, false)));
}
return img;
}
@ -1952,7 +1952,7 @@ PreLaunchWindow *PreLaunchWindowInstance = 0;
PreLaunchWindow::PreLaunchWindow(QString title) : TWidget(0) {
Fonts::start();
QIcon icon(QPixmap::fromImage(QImage(cPlatform() == dbipMac ? qsl(":/gui/art/iconbig256.png") : qsl(":/gui/art/icon256.png")), Qt::ColorOnly));
QIcon icon(App::pixmapFromImageInPlace(QImage(cPlatform() == dbipMac ? qsl(":/gui/art/iconbig256.png") : qsl(":/gui/art/icon256.png"))));
if (cPlatform() == dbipLinux32 || cPlatform() == dbipLinux64) {
icon = QIcon::fromTheme("telegram", icon);
}

View File

@ -484,14 +484,12 @@ void AudioPlayer::play(const AudioMsgId &audio, int64 position) {
if (stopped) emit updated(stopped);
}
void AudioPlayer::initFromVideo(const AudioMsgId &audio, uint64 videoPlayId, std_::unique_ptr<VideoSoundData> &&data, int64 position) {
t_assert(audio.type() == AudioMsgId::Type::Video);
auto type = audio.type();
void AudioPlayer::initFromVideo(uint64 videoPlayId, std_::unique_ptr<VideoSoundData> &&data, int64 position) {
AudioMsgId stopped;
{
QMutexLocker lock(&playerMutex);
auto type = AudioMsgId::Type::Video;
auto current = dataForType(type);
t_assert(current != nullptr);
@ -503,7 +501,7 @@ void AudioPlayer::initFromVideo(const AudioMsgId &audio, uint64 videoPlayId, std
}
emit faderOnTimer();
current->clear();
current->audio = audio;
current->audio = AudioMsgId(AudioMsgId::Type::Video);
current->videoPlayId = videoPlayId;
current->videoData = std_::move(data);
{
@ -516,7 +514,7 @@ void AudioPlayer::initFromVideo(const AudioMsgId &audio, uint64 videoPlayId, std
current->playbackState.state = AudioPlayerPaused;
current->loading = true;
emit loaderOnStart(audio, position);
emit loaderOnStart(current->audio, position);
}
if (stopped) emit updated(stopped);
}
@ -651,7 +649,7 @@ void AudioPlayer::videoSoundProgress(const AudioMsgId &audio) {
auto current = dataForType(type);
t_assert(current != nullptr);
if (current->videoPlayId == _lastVideoPlayId && current->playbackState.frequency) {
if (current->videoPlayId == _lastVideoPlayId && current->playbackState.duration && current->playbackState.frequency) {
_lastVideoPlaybackWhen = getms();
_lastVideoPlaybackCorrectedMs = (current->playbackState.position * 1000ULL) / current->playbackState.frequency;
}
@ -1523,15 +1521,11 @@ void AudioCaptureInner::onStop(bool needResult) {
if (d->device) {
alcCaptureStop(d->device);
alcCaptureCloseDevice(d->device);
d->device = 0;
d->device = nullptr;
if (d->ioContext) {
av_free(d->ioContext);
d->ioContext = 0;
}
if (d->codecContext) {
avcodec_close(d->codecContext);
d->codecContext = 0;
d->codecContext = nullptr;
}
if (d->srcSamplesData) {
if (d->srcSamplesData[0]) {
@ -1548,23 +1542,28 @@ void AudioCaptureInner::onStop(bool needResult) {
d->fullSamples = 0;
if (d->swrContext) {
swr_free(&d->swrContext);
d->swrContext = 0;
d->swrContext = nullptr;
}
if (d->opened) {
avformat_close_input(&d->fmtContext);
d->opened = false;
d->ioBuffer = 0;
}
if (d->ioContext) {
av_free(d->ioContext->buffer);
av_free(d->ioContext);
d->ioContext = nullptr;
d->ioBuffer = nullptr;
} else if (d->ioBuffer) {
av_free(d->ioBuffer);
d->ioBuffer = 0;
d->ioBuffer = nullptr;
}
if (d->fmtContext) {
avformat_free_context(d->fmtContext);
d->fmtContext = 0;
d->fmtContext = nullptr;
}
d->fmt = 0;
d->stream = 0;
d->codec = 0;
d->fmt = nullptr;
d->stream = nullptr;
d->codec = nullptr;
d->lastUpdate = 0;
d->levelMax = 0;

View File

@ -67,7 +67,7 @@ public:
void stop(AudioMsgId::Type type);
// Video player audio stream interface.
void initFromVideo(const AudioMsgId &audio, uint64 videoPlayId, std_::unique_ptr<VideoSoundData> &&data, int64 position);
void initFromVideo(uint64 videoPlayId, std_::unique_ptr<VideoSoundData> &&data, int64 position);
void feedFromVideo(VideoSoundPart &&part);
int64 getVideoCorrectedTime(uint64 playId, uint64 systemMs);
void videoSoundProgress(const AudioMsgId &audio);

View File

@ -76,9 +76,12 @@ bool AbstractFFMpegLoader::open(qint64 position) {
}
AbstractFFMpegLoader::~AbstractFFMpegLoader() {
if (ioContext) av_free(ioContext);
if (_opened) {
avformat_close_input(&fmtContext);
}
if (ioContext) {
av_free(ioContext->buffer);
av_free(ioContext);
} else if (ioBuffer) {
av_free(ioBuffer);
}
@ -221,9 +224,6 @@ bool FFMpegLoader::open(qint64 position) {
if (av_seek_frame(fmtContext, streamId, ts, 0) < 0) {
}
}
//if (dstSamplesData) {
// position = qRound(srcRate * (position / float64(dstRate)));
//}
}
return true;

View File

@ -201,7 +201,7 @@ void AudioPlayerLoaders::loadData(AudioMsgId audio, qint64 position) {
}
m->skipStart = position;
m->skipEnd = m->playbackState.duration - position;
m->playbackState.position = 0;
m->playbackState.position = position;
m->started = 0;
}
if (samplesCount) {

View File

@ -182,6 +182,7 @@ ChildFFMpegLoader::~ChildFFMpegLoader() {
for (auto &packet : queue) {
FFMpeg::freePacket(&packet);
}
if (_swrContext) swr_free(&_swrContext);
if (_dstSamplesData) {
if (_dstSamplesData[0]) {
av_freep(&_dstSamplesData[0]);

View File

@ -233,7 +233,7 @@ bool FFMpegReaderImplementation::renderFrame(QImage &to, bool &hasAlpha, const Q
}
// Read some future packets for audio stream.
if (_audioStreamId) {
if (_audioStreamId >= 0) {
while (_frameMs + 5000 > _lastReadPacketMs) {
auto packetResult = readPacket();
if (packetResult != PacketResult::Ok) {
@ -246,7 +246,7 @@ bool FFMpegReaderImplementation::renderFrame(QImage &to, bool &hasAlpha, const Q
return true;
}
bool FFMpegReaderImplementation::start(Mode mode) {
bool FFMpegReaderImplementation::start(Mode mode, int64 positionMs) {
_mode = mode;
initDevice();
@ -309,6 +309,7 @@ bool FFMpegReaderImplementation::start(Mode mode) {
return false;
}
std_::unique_ptr<VideoSoundData> soundData;
if (_audioStreamId >= 0) {
// Get a pointer to the codec context for the audio stream
auto audioContextOriginal = _fmtContext->streams[_audioStreamId]->codec;
@ -326,7 +327,7 @@ bool FFMpegReaderImplementation::start(Mode mode) {
return false;
}
auto soundData = std_::make_unique<VideoSoundData>();
soundData = std_::make_unique<VideoSoundData>();
soundData->context = audioContext;
soundData->frequency = audioContextOriginal->sample_rate;
if (_fmtContext->streams[_audioStreamId]->duration == AV_NOPTS_VALUE) {
@ -334,7 +335,20 @@ bool FFMpegReaderImplementation::start(Mode mode) {
} else {
soundData->length = (_fmtContext->streams[_audioStreamId]->duration * soundData->frequency * _fmtContext->streams[_audioStreamId]->time_base.num) / _fmtContext->streams[_audioStreamId]->time_base.den;
}
audioPlayer()->initFromVideo(AudioMsgId(AudioMsgId::Type::Video), _playId, std_::move(soundData), 0);
}
if (positionMs) {
int64 ts = (positionMs * _fmtContext->streams[_streamId]->time_base.den) / (1000LL * _fmtContext->streams[_streamId]->time_base.num);
if (av_seek_frame(_fmtContext, _streamId, ts, AVSEEK_FLAG_ANY) < 0) {
if (av_seek_frame(_fmtContext, _streamId, ts, 0) < 0) {
positionMs = 0;
}
}
}
if (_audioStreamId >= 0) {
int64 position = (positionMs * soundData->frequency) / 1000LL;
audioPlayer()->initFromVideo(_playId, std_::move(soundData), position);
}
return true;
@ -348,22 +362,26 @@ FFMpegReaderImplementation::~FFMpegReaderImplementation() {
if (_audioStreamId >= 0) {
audioPlayer()->stopFromVideo(_playId);
}
clearPacketQueue();
if (_frameRead) {
av_frame_unref(_frame);
_frameRead = false;
}
if (_ioContext) av_free(_ioContext);
if (_codecContext) avcodec_close(_codecContext);
if (_swsContext) sws_freeContext(_swsContext);
if (_opened) {
avformat_close_input(&_fmtContext);
}
if (_ioContext) {
av_free(_ioContext->buffer);
av_free(_ioContext);
} else if (_ioBuffer) {
av_free(_ioBuffer);
}
if (_fmtContext) avformat_free_context(_fmtContext);
av_frame_free(&_frame);
clearPacketQueue();
}
FFMpegReaderImplementation::PacketResult FFMpegReaderImplementation::readPacket() {

View File

@ -51,7 +51,7 @@ public:
void pauseAudio() override;
void resumeAudio() override;
bool start(Mode mode) override;
bool start(Mode mode, int64 positionMs) override;
QString logData() const;

View File

@ -58,7 +58,7 @@ public:
virtual void pauseAudio() = 0;
virtual void resumeAudio() = 0;
virtual bool start(Mode mode) = 0;
virtual bool start(Mode mode, int64 positionMs) = 0;
virtual ~ReaderImplementation() {
}
int64 dataSize() const {

View File

@ -99,7 +99,7 @@ int64 QtGifReaderImplementation::durationMs() const {
return 0; // not supported
}
bool QtGifReaderImplementation::start(Mode mode) {
bool QtGifReaderImplementation::start(Mode mode, int64 positionMs) {
if (mode == Mode::OnlyGifv) return false;
_mode = mode;
return jumpToStart();

View File

@ -47,7 +47,7 @@ public:
void resumeAudio() override {
}
bool start(Mode mode) override;
bool start(Mode mode, int64 positionMs) override;
~QtGifReaderImplementation();

View File

@ -85,10 +85,11 @@ QPixmap _prepareFrame(const FrameRequest &request, const QImage &original, bool
} // namespace
Reader::Reader(const FileLocation &location, const QByteArray &data, Callback &&callback, Mode mode)
Reader::Reader(const FileLocation &location, const QByteArray &data, Callback &&callback, Mode mode, int64 seekMs)
: _callback(std_::move(callback))
, _mode(mode)
, _playId(rand_value<uint64>()) {
, _playId(rand_value<uint64>())
, _seekPositionMs(seekMs) {
if (threads.size() < ClipThreadsCount) {
_threadIndex = threads.size();
threads.push_back(new QThread());
@ -269,7 +270,7 @@ int64 Reader::getPositionMs() const {
if (auto frame = frameToShow()) {
return frame->positionMs;
}
return 0;
return _seekPositionMs;
}
int64 Reader::getDurationMs() const {
@ -310,10 +311,12 @@ void Reader::stop() {
void Reader::error() {
_state = State::Error;
_private = nullptr;
}
void Reader::finished() {
_state = State::Finished;
_private = nullptr;
}
Reader::~Reader() {
@ -325,6 +328,7 @@ public:
ReaderPrivate(Reader *reader, const FileLocation &location, const QByteArray &data) : _interface(reader)
, _mode(reader->mode())
, _playId(reader->playId())
, _seekPositionMs(reader->seekPositionMs())
, _data(data) {
if (_data.isEmpty()) {
_location = std_::make_unique<FileLocation>(location);
@ -337,7 +341,7 @@ public:
}
ProcessResult start(uint64 ms) {
if (!_implementation && !init()) {
if (!_implementation && !init(_seekPositionMs)) {
return error();
}
if (frame() && frame()->original.isNull()) {
@ -348,6 +352,8 @@ public:
if (!_implementation->renderFrame(frame()->original, frame()->alpha, QSize())) {
return error();
}
frame()->positionMs = _implementation->frameRealTime();
_width = frame()->original.width();
_height = frame()->original.height();
_durationMs = _implementation->durationMs();
@ -381,7 +387,7 @@ public:
}
ProcessResult finishProcess(uint64 ms) {
auto readResult = _implementation->readFramesTill(ms - _animationStarted);
auto readResult = _implementation->readFramesTill(_skippedMs + ms - _animationStarted);
if (readResult == internal::ReaderImplementation::ReadResult::Eof) {
stop();
_state = State::Finished;
@ -391,6 +397,11 @@ public:
}
_nextFramePositionMs = _implementation->frameRealTime();
_nextFrameWhen = _animationStarted + _implementation->framePresentationTime();
if (static_cast<int64>(_nextFrameWhen) > _skippedMs) {
_nextFrameWhen -= _skippedMs;
} else {
_nextFrameWhen = 1;
}
if (!renderFrame()) {
return error();
@ -411,7 +422,7 @@ public:
return true;
}
bool init() {
bool init(int64 positionMs) {
if (_data.isEmpty() && QFileInfo(_location->name()).size() <= AnimationInMemory) {
QFile f(_location->name());
if (f.open(QIODevice::ReadOnly)) {
@ -432,7 +443,8 @@ public:
}
return ImplementationMode::Normal;
};
return _implementation->start(implementationMode());
_skippedMs = positionMs;
return _implementation->start(implementationMode(), positionMs);
}
void startedAt(uint64 ms) {
@ -485,6 +497,7 @@ private:
State _state = State::Reading;
Reader::Mode _mode;
uint64 _playId;
int64 _seekPositionMs = 0;
QByteArray _data;
std_::unique_ptr<FileLocation> _location;
@ -517,6 +530,7 @@ private:
uint64 _animationStarted = 0;
uint64 _nextFrameWhen = 0;
int64 _nextFramePositionMs = 0;
int64 _skippedMs = 0;
bool _autoPausedGif = false;
bool _started = false;
@ -699,11 +713,12 @@ void Manager::process() {
_timer.stop();
_processingInThread = thread();
bool checkAllReaders = false;
uint64 ms = getms(), minms = ms + 86400 * 1000ULL;
{
QReadLocker lock(&_readerPointersMutex);
for (auto it = _readerPointers.begin(), e = _readerPointers.end(); it != e; ++it) {
if (it->v.loadAcquire()) {
if (it->v.loadAcquire() && it.key()->_private != nullptr) {
auto i = _readers.find(it.key()->_private);
if (i == _readers.cend()) {
_readers.insert(it.key()->_private, 0);
@ -723,6 +738,7 @@ void Manager::process() {
it->v.storeRelease(0);
}
}
checkAllReaders = (_readers.size() > _readerPointers.size());
}
for (auto i = _readers.begin(), e = _readers.end(); i != e;) {
@ -744,6 +760,15 @@ void Manager::process() {
} else {
i.value() = (ms + 86400 * 1000ULL);
}
} else if (checkAllReaders) {
QReadLocker lock(&_readerPointersMutex);
ReaderPointers::const_iterator it = constUnsafeFindReaderPointer(reader);
if (it == _readerPointers.cend()) {
_loadLevel.fetchAndAddRelaxed(-1 * (reader->_width > 0 ? reader->_width * reader->_height : AverageGifSize));
delete reader;
i = _readers.erase(i);
continue;
}
}
if (!reader->_autoPausedGif && i.value() < minms) {
minms = i.value();
@ -771,7 +796,7 @@ void Manager::clear() {
{
QWriteLocker lock(&_readerPointersMutex);
for (ReaderPointers::iterator it = _readerPointers.begin(), e = _readerPointers.end(); it != e; ++it) {
it.key()->_private = 0;
it.key()->_private = nullptr;
}
_readerPointers.clear();
}
@ -792,7 +817,7 @@ MTPDocumentAttribute readAttributes(const QString &fname, const QByteArray &data
auto playId = 0ULL;
auto reader = std_::make_unique<internal::FFMpegReaderImplementation>(&localloc, &localdata, playId);
if (reader->start(internal::ReaderImplementation::Mode::OnlyGifv)) {
if (reader->start(internal::ReaderImplementation::Mode::OnlyGifv, 0)) {
bool hasAlpha = false;
auto readResult = reader->readFramesTill(-1);
auto readFrame = (readResult == internal::ReaderImplementation::ReadResult::Success);

View File

@ -58,7 +58,7 @@ public:
Video,
};
Reader(const FileLocation &location, const QByteArray &data, Callback &&callback, Mode mode = Mode::Gif);
Reader(const FileLocation &location, const QByteArray &data, Callback &&callback, Mode mode = Mode::Gif, int64 seekMs = 0);
static void callback(Reader *reader, int threadIndex, Notification notification); // reader can be deleted
void setAutoplay() {
@ -71,6 +71,9 @@ public:
uint64 playId() const {
return _playId;
}
int64 seekPositionMs() const {
return _seekPositionMs;
}
void start(int framew, int frameh, int outerw, int outerh, bool rounded);
QPixmap current(int framew, int frameh, int outerw, int outerh, uint64 ms);
@ -128,6 +131,7 @@ private:
uint64 _playId;
bool _hasAudio = false;
int64 _durationMs = 0;
int64 _seekPositionMs = 0;
mutable int _width = 0;
mutable int _height = 0;

View File

@ -48,19 +48,29 @@ Controller::Controller(QWidget *parent) : TWidget(parent)
connect(_playPauseResume, SIGNAL(clicked()), this, SIGNAL(playPressed()));
connect(_fullScreenToggle, SIGNAL(clicked()), this, SIGNAL(toFullScreenPressed()));
connect(_playback, SIGNAL(seekProgress(int64)), this, SLOT(onSeekProgress(int64)));
connect(_playback, SIGNAL(seekFinished(int64)), this, SLOT(onSeekFinished(int64)));
connect(_playback, SIGNAL(seekProgress(float64)), this, SLOT(onSeekProgress(float64)));
connect(_playback, SIGNAL(seekFinished(float64)), this, SLOT(onSeekFinished(float64)));
connect(_volumeController, SIGNAL(volumeChanged(float64)), this, SIGNAL(volumeChanged(float64)));
}
void Controller::onSeekProgress(int64 position) {
_seekPosition = position;
emit seekProgress(position);
void Controller::onSeekProgress(float64 progress) {
if (!_lastDurationMs) return;
auto positionMs = snap(static_cast<int64>(progress * _lastDurationMs), 0LL, _lastDurationMs);
if (_seekPositionMs != positionMs) {
_seekPositionMs = positionMs;
emit seekProgress(positionMs);
refreshTimeTexts();
}
}
void Controller::onSeekFinished(int64 position) {
_seekPosition = -1;
emit seekFinished(position);
void Controller::onSeekFinished(float64 progress) {
if (!_lastDurationMs) return;
auto positionMs = snap(static_cast<int64>(progress * _lastDurationMs), 0LL, _lastDurationMs);
_seekPositionMs = -1;
emit seekFinished(positionMs);
refreshTimeTexts();
}
void Controller::showAnimated() {
@ -89,14 +99,14 @@ void Controller::fadeUpdated(float64 opacity) {
_playback->setFadeOpacity(opacity);
}
void Controller::updatePlayback(const AudioPlaybackState &playbackState) {
void Controller::updatePlayback(const AudioPlaybackState &playbackState, bool reset) {
updatePlayPauseResumeState(playbackState);
_playback->updateState(playbackState);
_playback->updateState(playbackState, reset);
updateTimeTexts(playbackState);
}
void Controller::updatePlayPauseResumeState(const AudioPlaybackState &playbackState) {
bool showPause = (playbackState.state == AudioPlayerPlaying || playbackState.state == AudioPlayerResuming);
bool showPause = (playbackState.state == AudioPlayerPlaying || playbackState.state == AudioPlayerResuming || _seekPositionMs >= 0);
if (showPause != _showPause) {
disconnect(_playPauseResume, SIGNAL(clicked()), this, _showPause ? SIGNAL(pausePressed()) : SIGNAL(playPressed()));
_showPause = showPause;
@ -120,11 +130,30 @@ void Controller::updateTimeTexts(const AudioPlaybackState &playbackState) {
auto playAlready = position / playFrequency;
auto playLeft = (playbackState.duration / playFrequency) - playAlready;
auto timeAlready = formatDurationText(playAlready);
auto minus = QChar(8722);
auto timeLeft = minus + formatDurationText(playLeft);
_lastDurationMs = (playbackState.duration * 1000LL) / playFrequency;
_timeAlready = formatDurationText(playAlready);
auto minus = QChar(8722);
_timeLeft = minus + formatDurationText(playLeft);
if (_seekPositionMs < 0) {
refreshTimeTexts();
}
}
void Controller::refreshTimeTexts() {
auto alreadyChanged = false, leftChanged = false;
auto timeAlready = _timeAlready;
auto timeLeft = _timeLeft;
if (_seekPositionMs >= 0) {
auto playAlready = _seekPositionMs / 1000LL;
auto playLeft = (_lastDurationMs / 1000LL) - playAlready;
timeAlready = formatDurationText(playAlready);
auto minus = QChar(8722);
timeLeft = minus + formatDurationText(playLeft);
}
_playedAlready->setText(timeAlready, &alreadyChanged);
_toPlayLeft->setText(timeLeft, &leftChanged);
if (alreadyChanged || leftChanged) {

View File

@ -43,7 +43,7 @@ public:
void showAnimated();
void hideAnimated();
void updatePlayback(const AudioPlaybackState &playbackState);
void updatePlayback(const AudioPlaybackState &playbackState, bool reset);
void setInFullScreen(bool inFullScreen);
void grabStart() override;
@ -52,15 +52,15 @@ public:
signals:
void playPressed();
void pausePressed();
void seekProgress(int64 position);
void seekFinished(int64 position);
void seekProgress(int64 positionMs);
void seekFinished(int64 positionMs);
void volumeChanged(float64 volume);
void toFullScreenPressed();
void fromFullScreenPressed();
private slots:
void onSeekProgress(int64 position);
void onSeekFinished(int64 position);
void onSeekProgress(float64 progress);
void onSeekFinished(float64 progress);
protected:
void resizeEvent(QResizeEvent *e) override;
@ -75,9 +75,12 @@ private:
void updatePlayPauseResumeState(const AudioPlaybackState &playbackState);
void updateTimeTexts(const AudioPlaybackState &playbackState);
void refreshTimeTexts();
bool _showPause = false;
int64 _seekPosition = -1;
QString _timeAlready, _timeLeft;
int64 _seekPositionMs = -1;
int64 _lastDurationMs = 0;
ChildWidget<Ui::IconButton> _playPauseResume;
ChildWidget<Playback> _playback;

View File

@ -32,11 +32,11 @@ Playback::Playback(QWidget *parent) : TWidget(parent)
setCursor(style::cur_pointer);
}
void Playback::updateState(const AudioPlaybackState &playbackState) {
void Playback::updateState(const AudioPlaybackState &playbackState, bool reset) {
qint64 position = 0, duration = playbackState.duration;
_playing = !(playbackState.state & AudioPlayerStoppedMask);
if (_playing && playbackState.state != AudioPlayerFinishing) {
if (_playing || playbackState.state == AudioPlayerStopped) {
position = playbackState.position;
} else if (playbackState.state == AudioPlayerStoppedAtEnd) {
position = playbackState.duration;
@ -51,7 +51,7 @@ void Playback::updateState(const AudioPlaybackState &playbackState) {
progress = duration ? snap(float64(position) / duration, 0., 1.) : 0.;
}
if (duration != _duration || position != _position) {
if (duration && _duration && playbackState.state != AudioPlayerStopped) {
if (duration && _duration && !reset) {
a_progress.start(progress);
_a_progress.start();
} else {
@ -112,12 +112,26 @@ void Playback::paintEvent(QPaintEvent *e) {
}
void Playback::mouseMoveEvent(QMouseEvent *e) {
if (_mouseDown) {
_downProgress = snap(e->pos().x() / float64(width()), 0., 1.);
emit seekProgress(_downProgress);
update();
}
}
void Playback::mousePressEvent(QMouseEvent *e) {
_mouseDown = true;
_downProgress = snap(e->pos().x() / float64(width()), 0., 1.);
emit seekProgress(_downProgress);
update();
}
void Playback::mouseReleaseEvent(QMouseEvent *e) {
if (_mouseDown) {
_mouseDown = false;
emit seekFinished(_downProgress);
update();
}
}
void Playback::enterEvent(QEvent *e) {

View File

@ -31,12 +31,12 @@ class Playback : public TWidget {
public:
Playback(QWidget *parent);
void updateState(const AudioPlaybackState &playbackState);
void updateState(const AudioPlaybackState &playbackState, bool reset);
void setFadeOpacity(float64 opacity);
signals:
void seekProgress(int64 position);
void seekFinished(int64 position);
void seekProgress(float64 progress);
void seekFinished(float64 progress);
protected:
void paintEvent(QPaintEvent *e) override;

View File

@ -236,6 +236,7 @@ bool MediaView::gifShown() const {
void MediaView::stopGif() {
_gif = nullptr;
_videoPaused = _videoIsSilent = false;
_clipController.destroy();
Sandbox::removeEventFilter(this);
if (audioPlayer()) {
@ -1121,7 +1122,7 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
const FileLocation &location(_doc->location(true));
if (location.accessEnable()) {
if (QImageReader(location.name()).canRead()) {
_current = QPixmap::fromImage(App::readImage(location.name(), 0, false), Qt::ColorOnly);
_current = App::pixmapFromImageInPlace(App::readImage(location.name(), 0, false));
}
}
location.accessDisable();
@ -1258,7 +1259,7 @@ void MediaView::createClipReader() {
_gif = std_::make_unique<Media::Clip::Reader>(_doc->location(), _doc->data(), func(this, &MediaView::clipCallback), mode);
// Correct values will be set when gif gets inited.
_videoIsSilent = false;
_videoPaused = _videoIsSilent = false;
_videoPositionMs = 0ULL;
_videoDurationMs = _doc->duration() * 1000ULL;
@ -1306,21 +1307,7 @@ void MediaView::onVideoPauseResume() {
if (_gif->state() == Media::Clip::State::Error) {
displayDocument(_doc, item);
} else if (_gif->state() == Media::Clip::State::Finished) {
_autoplayVideoDocument = _doc;
_current = _gif->current(_gif->width(), _gif->height(), _gif->width(), _gif->height(), getms());
_gif = std_::make_unique<Media::Clip::Reader>(_doc->location(), _doc->data(), func(this, &MediaView::clipCallback), Media::Clip::Reader::Mode::Video);
// Correct values will be set when gif gets inited.
_videoIsSilent = false;
_videoPositionMs = 0;
AudioPlaybackState state;
state.state = AudioPlayerStopped;
state.position = _videoPositionMs;
state.duration = _videoDurationMs;
state.frequency = _videoFrequencyMs;
updateVideoPlaybackState(state);
restartVideoAtSeekPosition(0);
} else {
_gif->pauseResumeVideo();
_videoPaused = _gif->videoPaused();
@ -1333,12 +1320,34 @@ void MediaView::onVideoPauseResume() {
}
}
void MediaView::onVideoSeekProgress(int64 position) {
void MediaView::restartVideoAtSeekPosition(int64 positionMs) {
_autoplayVideoDocument = _doc;
if (_current.isNull()) {
_current = _gif->current(_gif->width(), _gif->height(), _gif->width(), _gif->height(), getms());
}
_gif = std_::make_unique<Media::Clip::Reader>(_doc->location(), _doc->data(), func(this, &MediaView::clipCallback), Media::Clip::Reader::Mode::Video, positionMs);
// Correct values will be set when gif gets inited.
_videoPaused = _videoIsSilent = false;
_videoPositionMs = positionMs;
AudioPlaybackState state;
state.state = AudioPlayerPlaying;
state.position = _videoPositionMs;
state.duration = _videoDurationMs;
state.frequency = _videoFrequencyMs;
updateVideoPlaybackState(state, true);
}
void MediaView::onVideoSeekFinished(int64 position) {
void MediaView::onVideoSeekProgress(int64 positionMs) {
if (!_videoPaused) {
onVideoPauseResume();
}
}
void MediaView::onVideoSeekFinished(int64 positionMs) {
restartVideoAtSeekPosition(positionMs);
}
void MediaView::onVideoVolumeChanged(float64 volume) {
@ -1361,12 +1370,14 @@ void MediaView::onVideoPlayProgress(const AudioMsgId &audioId) {
t_assert(audioPlayer() != nullptr);
auto state = audioPlayer()->currentVideoState(_gif->playId());
updateVideoPlaybackState(state);
if (state.duration) {
updateVideoPlaybackState(state);
}
}
void MediaView::updateVideoPlaybackState(const AudioPlaybackState &state) {
void MediaView::updateVideoPlaybackState(const AudioPlaybackState &state, bool reset) {
if (state.frequency) {
_clipController->updatePlayback(state);
_clipController->updatePlayback(state, reset);
} else { // Audio has stopped already.
_videoIsSilent = true;
updateSilentVideoPlaybackState();

View File

@ -118,8 +118,8 @@ protected:
private slots:
void onVideoPauseResume();
void onVideoSeekProgress(int64 position);
void onVideoSeekFinished(int64 position);
void onVideoSeekProgress(int64 positionMs);
void onVideoSeekFinished(int64 positionMs);
void onVideoVolumeChanged(float64 volume);
void onVideoToFullScreen();
void onVideoFromFullScreen();
@ -131,8 +131,9 @@ private:
void findCurrent();
void loadBack();
void updateVideoPlaybackState(const AudioPlaybackState &state);
void updateVideoPlaybackState(const AudioPlaybackState &state, bool reset = false);
void updateSilentVideoPlaybackState();
void restartVideoAtSeekPosition(int64 positionMs);
void createClipController();
void setClipControllerGeometry();

View File

@ -105,9 +105,10 @@ void FileLoader::readImage(const QSize &shrinkBox) const {
QImage image = App::readImage(_data, &format, false);
if (!image.isNull()) {
if (!shrinkBox.isEmpty() && (image.width() > shrinkBox.width() || image.height() > shrinkBox.height())) {
image = image.scaled(shrinkBox, Qt::KeepAspectRatio, Qt::SmoothTransformation);
_imagePixmap = App::pixmapFromImageInPlace(image.scaled(shrinkBox, Qt::KeepAspectRatio, Qt::SmoothTransformation));
} else {
_imagePixmap = App::pixmapFromImageInPlace(std_::move(image));
}
_imagePixmap = QPixmap::fromImage(image, Qt::ColorOnly);
_imageFormat = format;
}
}

View File

@ -202,7 +202,7 @@ void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const
img.setDevicePixelRatio(cRetinaFactor());
_data->forget();
_pix = QPixmap::fromImage(img, Qt::ColorOnly);
_pix = App::pixmapFromImageInPlace(std_::move(img));
} else if (!_pix.isNull()) {
_pix = QPixmap();
}
@ -274,7 +274,7 @@ void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const
img.setDevicePixelRatio(cRetinaFactor());
_data->forget();
_pix = QPixmap::fromImage(img, Qt::ColorOnly);
_pix = App::pixmapFromImageInPlace(std_::move(img));
} else if (!_pix.isNull()) {
_pix = QPixmap();
}

View File

@ -360,8 +360,8 @@ void MainWindow::psUpdateCounter() {
bool muted = App::histories().unreadOnlyMuted();
style::color bg = muted ? st::counterMuteBG : st::counterBG;
icon.addPixmap(QPixmap::fromImage(iconWithCounter(16, counter, bg, true), Qt::ColorOnly));
icon.addPixmap(QPixmap::fromImage(iconWithCounter(32, counter, bg, true), Qt::ColorOnly));
icon.addPixmap(App::pixmapFromImageInPlace(iconWithCounter(16, counter, bg, true), Qt::ColorOnly));
icon.addPixmap(App::pixmapFromImageInPlace(iconWithCounter(32, counter, bg, true), Qt::ColorOnly));
}
trayIcon->setIcon(icon);
}

View File

@ -212,8 +212,8 @@ void MainWindow::psUpdateCounter() {
int32 size = cRetina() ? 44 : 22;
_placeCounter(img, size, counter, bg, (dm && muted) ? st::counterMacInvColor : st::counterColor);
_placeCounter(imgsel, size, counter, st::white, st::counterMacInvColor);
icon.addPixmap(QPixmap::fromImage(img, Qt::ColorOnly));
icon.addPixmap(QPixmap::fromImage(imgsel, Qt::ColorOnly), QIcon::Selected);
icon.addPixmap(App::pixmapFromImageInPlace(std_::move(img)));
icon.addPixmap(App::pixmapFromImageInPlace(std_::move(imgsel)), QIcon::Selected);
trayIcon->setIcon(icon);
}
}

View File

@ -736,10 +736,10 @@ void MainWindow::psUpdateCounter() {
style::color bg = muted ? st::counterMuteBG : st::counterBG;
QIcon iconSmall, iconBig;
iconSmall.addPixmap(QPixmap::fromImage(iconWithCounter(16, counter, bg, true), Qt::ColorOnly));
iconSmall.addPixmap(QPixmap::fromImage(iconWithCounter(32, counter, bg, true), Qt::ColorOnly));
iconBig.addPixmap(QPixmap::fromImage(iconWithCounter(32, taskbarList.Get() ? 0 : counter, bg, false), Qt::ColorOnly));
iconBig.addPixmap(QPixmap::fromImage(iconWithCounter(64, taskbarList.Get() ? 0 : counter, bg, false), Qt::ColorOnly));
iconSmall.addPixmap(App::pixmapFromImageInPlace(iconWithCounter(16, counter, bg, true)));
iconSmall.addPixmap(App::pixmapFromImageInPlace(iconWithCounter(32, counter, bg, true)));
iconBig.addPixmap(App::pixmapFromImageInPlace(iconWithCounter(32, taskbarList.Get() ? 0 : counter, bg, false)));
iconBig.addPixmap(App::pixmapFromImageInPlace(iconWithCounter(64, taskbarList.Get() ? 0 : counter, bg, false)));
if (trayIcon) {
trayIcon->setIcon(iconSmall);
}
@ -753,8 +753,8 @@ void MainWindow::psUpdateCounter() {
if (taskbarList.Get()) {
if (counter > 0) {
QIcon iconOverlay;
iconOverlay.addPixmap(QPixmap::fromImage(iconWithCounter(-16, counter, bg, false), Qt::ColorOnly));
iconOverlay.addPixmap(QPixmap::fromImage(iconWithCounter(-32, counter, bg, false), Qt::ColorOnly));
iconOverlay.addPixmap(App::pixmapFromImageInPlace(iconWithCounter(-16, counter, bg, false)));
iconOverlay.addPixmap(App::pixmapFromImageInPlace(iconWithCounter(-32, counter, bg, false)));
ps_iconOverlay = createHIconFromQIcon(iconOverlay, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
}
QString description = counter > 0 ? QString("%1 unread messages").arg(counter) : qsl("No unread messages");

View File

@ -585,7 +585,7 @@ namespace {
if (!iconindex) { // try to read image
QImage img(QString::fromWCharArray(icon));
if (!img.isNull()) {
return qt_pixmapToWinHBITMAP(QPixmap::fromImage(img.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)), /* HBitmapAlpha */ 2);
return qt_pixmapToWinHBITMAP(App::pixmapFromImageInPlace(img.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)), /* HBitmapAlpha */ 2);
}
}
return 0;

View File

@ -1753,7 +1753,7 @@ void SettingsInner::updateChatBackground() {
p.setRenderHint(QPainter::SmoothPixmapTransform);
p.drawPixmap(0, 0, st::setBackgroundSize, st::setBackgroundSize, pix, sx, sy, s, s);
}
_background = QPixmap::fromImage(back);
_background = App::pixmapFromImageInPlace(std_::move(back));
_background.setDevicePixelRatio(cRetinaFactor());
_needBackgroundUpdate = false;

View File

@ -220,7 +220,7 @@ void UserData::setPhoto(const MTPUserProfilePhoto &p) { // see Local::readPeer a
newPhotoId = 0;
if (id == ServiceUserId) {
if (_userpic.v() == userDefPhoto(colorIndex).v()) {
newPhoto = ImagePtr(QPixmap::fromImage(App::wnd()->iconLarge().scaledToWidth(160, Qt::SmoothTransformation), Qt::ColorOnly), "PNG");
newPhoto = ImagePtr(App::pixmapFromImageInPlace(App::wnd()->iconLarge().scaledToWidth(160, Qt::SmoothTransformation)), "PNG");
}
} else {
newPhoto = userDefPhoto(colorIndex);
@ -299,12 +299,11 @@ void UserData::setBotInfoVersion(int version) {
botInfo->commands.clear();
Notify::botCommandsChanged(this);
}
delete botInfo;
botInfo = 0;
botInfo = nullptr;
Notify::userIsBotChanged(this);
}
} else if (!botInfo) {
botInfo = new BotInfo();
botInfo = std_::make_unique<BotInfo>();
botInfo->version = version;
Notify::userIsBotChanged(this);
} else if (botInfo->version < version) {

View File

@ -471,7 +471,7 @@ public:
return _about;
}
BotInfo *botInfo = nullptr;
std_::unique_ptr<BotInfo> botInfo;
QString restrictionReason() const override {
return _restrictionReason;

View File

@ -279,7 +279,7 @@ void TitleWidget::updateCounter() {
case dbisOneAndHalf: size = -24; break;
case dbisTwo: size = -32; break;
}
_counter = QPixmap::fromImage(App::wnd()->iconWithCounter(size, counter, bg, false), Qt::ColorOnly);
_counter = App::pixmapFromImageInPlace(App::wnd()->iconWithCounter(size, counter, bg, false));
_counter.setDevicePixelRatio(cRetinaFactor());
update(QRect(st::titleIconPos, st::titleIconImg.pxSize()));
} else {

View File

@ -56,8 +56,6 @@ BoxShadow::BoxShadow(const style::sprite &topLeft) : _size(topLeft.pxWidth()), _
m.setDevicePixelRatio(cRetinaFactor());
p.drawImage(_size, 0, m, _pixsize, 0, _pixsize, _pixsize * 2);
}
_corners = QPixmap::fromImage(cornersImage, Qt::ColorOnly);
_corners.setDevicePixelRatio(cRetinaFactor());
_colors.reserve(_pixsize);
uchar prev = 0;
for (int i = 0; i < _pixsize; ++i) {
@ -68,15 +66,17 @@ BoxShadow::BoxShadow(const style::sprite &topLeft) : _size(topLeft.pxWidth()), _
prev = a;
}
if (cRetina()) {
_left = QPixmap::fromImage(cornersImage.copy(0, _pixsize - 1, _colors.size(), 1), Qt::ColorOnly);
_left = App::pixmapFromImageInPlace(cornersImage.copy(0, _pixsize - 1, _colors.size(), 1));
_left.setDevicePixelRatio(cRetinaFactor());
_top = QPixmap::fromImage(cornersImage.copy(_pixsize - 1, 0, 1, _colors.size()), Qt::ColorOnly);
_top = App::pixmapFromImageInPlace(cornersImage.copy(_pixsize - 1, 0, 1, _colors.size()));
_top.setDevicePixelRatio(cRetinaFactor());
_right = QPixmap::fromImage(cornersImage.copy(_pixsize * 2 - _colors.size(), _pixsize, _colors.size(), 1), Qt::ColorOnly);
_right = App::pixmapFromImageInPlace(cornersImage.copy(_pixsize * 2 - _colors.size(), _pixsize, _colors.size(), 1));
_right.setDevicePixelRatio(cRetinaFactor());
_bottom = QPixmap::fromImage(cornersImage.copy(_pixsize, _pixsize * 2 - _colors.size(), 1, _colors.size()), Qt::ColorOnly);
_bottom = App::pixmapFromImageInPlace(cornersImage.copy(_pixsize, _pixsize * 2 - _colors.size(), 1, _colors.size()));
_bottom.setDevicePixelRatio(cRetinaFactor());
}
_corners = App::pixmapFromImageInPlace(std_::move(cornersImage));
_corners.setDevicePixelRatio(cRetinaFactor());
}
void BoxShadow::paint(QPainter &p, const QRect &box, int32 shifty, int32 flags) {
@ -140,8 +140,6 @@ RectShadow::RectShadow(const style::icon &topLeft) : _size(topLeft.width()), _pi
m.setDevicePixelRatio(cRetinaFactor());
p.drawImage(_size, 0, m, _pixsize, 0, _pixsize, _pixsize * 2);
}
_corners = QPixmap::fromImage(cornersImage, Qt::ColorOnly);
_corners.setDevicePixelRatio(cRetinaFactor());
uchar prev = 0;
for (int i = 0; i < _pixsize; ++i) {
@ -152,14 +150,17 @@ RectShadow::RectShadow(const style::icon &topLeft) : _size(topLeft.width()), _pi
prev = a;
}
_left = QPixmap::fromImage(cornersImage.copy(0, _pixsize - 1, _thickness, 1), Qt::ColorOnly);
_left = App::pixmapFromImageInPlace(cornersImage.copy(0, _pixsize - 1, _thickness, 1));
_left.setDevicePixelRatio(cRetinaFactor());
_top = QPixmap::fromImage(cornersImage.copy(_pixsize - 1, 0, 1, _thickness), Qt::ColorOnly);
_top = App::pixmapFromImageInPlace(cornersImage.copy(_pixsize - 1, 0, 1, _thickness));
_top.setDevicePixelRatio(cRetinaFactor());
_right = QPixmap::fromImage(cornersImage.copy(_pixsize * 2 - _thickness, _pixsize, _thickness, 1), Qt::ColorOnly);
_right = App::pixmapFromImageInPlace(cornersImage.copy(_pixsize * 2 - _thickness, _pixsize, _thickness, 1));
_right.setDevicePixelRatio(cRetinaFactor());
_bottom = QPixmap::fromImage(cornersImage.copy(_pixsize, _pixsize * 2 - _thickness, 1, _thickness), Qt::ColorOnly);
_bottom = App::pixmapFromImageInPlace(cornersImage.copy(_pixsize, _pixsize * 2 - _thickness, 1, _thickness));
_bottom.setDevicePixelRatio(cRetinaFactor());
_corners = App::pixmapFromImageInPlace(std_::move(cornersImage));
_corners.setDevicePixelRatio(cRetinaFactor());
}
void RectShadow::paint(Painter &p, const QRect &box, int shifty, Sides sides) {

View File

@ -106,7 +106,7 @@ CountryInput::CountryInput(QWidget *parent, const style::countryInput &st) : QWi
p.setBrush(_st.bgColor->b);
p.drawPolygon(trPoints, 3);
}
_arrow = QPixmap::fromImage(trImage, Qt::ColorOnly);
_arrow = App::pixmapFromImageInPlace(std_::move(trImage));
_inner = QRect(0, 0, _st.width, _st.height);
_arrowRect = QRect((st::inpIntroCountryCode.width - _arrow.width() - 1) / 2, _st.height, _arrow.width(), _arrow.height());
}

View File

@ -64,7 +64,7 @@ ImagePtr::ImagePtr(int32 width, int32 height, const MTPFileLocation &location, I
}
Image::Image(const QString &file, QByteArray fmt) : _forgot(false) {
_data = QPixmap::fromImage(App::readImage(file, &fmt, false, 0, &_saved), Qt::ColorOnly);
_data = App::pixmapFromImageInPlace(App::readImage(file, &fmt, false, 0, &_saved));
_format = fmt;
if (!_data.isNull()) {
globalAcquiredSize += int64(_data.width()) * _data.height() * 4;
@ -72,7 +72,7 @@ Image::Image(const QString &file, QByteArray fmt) : _forgot(false) {
}
Image::Image(const QByteArray &filecontent, QByteArray fmt) : _forgot(false) {
_data = QPixmap::fromImage(App::readImage(filecontent, &fmt, false), Qt::ColorOnly);
_data = App::pixmapFromImageInPlace(App::readImage(filecontent, &fmt, false));
_format = fmt;
_saved = filecontent;
if (!_data.isNull()) {
@ -420,7 +420,7 @@ const QPixmap &circleMask(int width, int height) {
p.drawEllipse(0, 0, width, height);
}
mask.setDevicePixelRatio(cRetinaFactor());
i = masks.insert(key, QPixmap::fromImage(mask));
i = masks.insert(key, App::pixmapFromImageInPlace(std_::move(mask)));
}
return i.value();
}
@ -543,7 +543,7 @@ QPixmap imagePix(QImage img, int32 w, int32 h, ImagePixOptions options, int32 ou
imageRound(img, ImageRoundRadius::Small);
}
img.setDevicePixelRatio(cRetinaFactor());
return QPixmap::fromImage(img, Qt::ColorOnly);
return App::pixmapFromImageInPlace(std_::move(img));
}
QPixmap Image::pixNoCache(int w, int h, ImagePixOptions options, int outerw, int outerh) const {
@ -584,7 +584,7 @@ QPixmap Image::pixNoCache(int w, int h, ImagePixOptions options, int outerw, int
} else if (options.testFlag(ImagePixRoundedSmall)) {
imageRound(result, ImageRoundRadius::Small);
}
return QPixmap::fromImage(result, Qt::ColorOnly);
return App::pixmapFromImageInPlace(std_::move(result));
}
return imagePix(_data.toImage(), w, h, options, outerw, outerh);
@ -596,11 +596,11 @@ QPixmap Image::pixColoredNoCache(const style::color &add, int32 w, int32 h, bool
if (_data.isNull()) return blank()->pix();
QImage img = _data.toImage();
if (w <= 0 || !width() || !height() || (w == width() && (h <= 0 || h == height()))) return QPixmap::fromImage(imageColored(add, img));
if (w <= 0 || !width() || !height() || (w == width() && (h <= 0 || h == height()))) return App::pixmapFromImageInPlace(imageColored(add, img));
if (h <= 0) {
return QPixmap::fromImage(imageColored(add, img.scaledToWidth(w, smooth ? Qt::SmoothTransformation : Qt::FastTransformation)), Qt::ColorOnly);
return App::pixmapFromImageInPlace(imageColored(add, img.scaledToWidth(w, smooth ? Qt::SmoothTransformation : Qt::FastTransformation)));
}
return QPixmap::fromImage(imageColored(add, img.scaled(w, h, Qt::IgnoreAspectRatio, smooth ? Qt::SmoothTransformation : Qt::FastTransformation)), Qt::ColorOnly);
return App::pixmapFromImageInPlace(imageColored(add, img.scaled(w, h, Qt::IgnoreAspectRatio, smooth ? Qt::SmoothTransformation : Qt::FastTransformation)));
}
QPixmap Image::pixBlurredColoredNoCache(const style::color &add, int32 w, int32 h) const {
@ -615,7 +615,7 @@ QPixmap Image::pixBlurredColoredNoCache(const style::color &add, int32 w, int32
img = img.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}
return QPixmap::fromImage(imageColored(add, img), Qt::ColorOnly);
return App::pixmapFromImageInPlace(imageColored(add, img));
}
void Image::forget() const {
@ -738,7 +738,7 @@ void RemoteImage::setData(QByteArray &bytes, const QByteArray &bytesFormat) {
globalAcquiredSize -= int64(_data.width()) * _data.height() * 4;
}
QByteArray fmt(bytesFormat);
_data = QPixmap::fromImage(App::readImage(bytes, &fmt, false), Qt::ColorOnly);
_data = App::pixmapFromImageInPlace(App::readImage(bytes, &fmt, false));
if (!_data.isNull()) {
globalAcquiredSize += int64(_data.width()) * _data.height() * 4;
setInformation(bytes.size(), _data.width(), _data.height());

View File

@ -73,6 +73,8 @@ void stopManager() {
internal::stopModules();
internal::destroyFonts();
internal::destroyColors();
internal::destroyIcons();
internal::destroySprite();
}
QImage colorizeImage(const QImage &src, const color &c, const QRect &r) {

View File

@ -64,7 +64,7 @@ QPixmap createIconPixmap(const IconMask *mask, const Color &color) {
}
finalImage = colorizeImage(maskImage, color, r);
finalImage.setDevicePixelRatio(cRetinaFactor());
return QPixmap::fromImage(finalImage, Qt::ColorOnly);
return App::pixmapFromImageInPlace(std_::move(finalImage));
}
} // namespace

View File

@ -131,5 +131,7 @@ private:
};
void destroyIcons();
} // namespace internal
} // namespace style

View File

@ -41,7 +41,7 @@ void loadSprite() {
}
QString spriteFile = qsl(":/gui/art/sprite") + spriteFilePostfix + qsl(".png");
if (rtl()) {
spriteData = new QPixmap(QPixmap::fromImage(QImage(spriteFile).mirrored(true, false)));
spriteData = new QPixmap(App::pixmapFromImageInPlace(QImage(spriteFile).mirrored(true, false)));
} else {
spriteData = new QPixmap(spriteFile);
}
@ -53,6 +53,11 @@ int spriteWidth() {
return spriteWidthValue;
}
void destroySprite() {
delete spriteData;
spriteData = nullptr;
}
} // namespace internal
const QPixmap &spritePixmap() {

View File

@ -37,6 +37,7 @@ namespace internal {
void loadSprite();
int spriteWidth();
void destroySprite();
class Sprite {
public:

View File

@ -337,14 +337,7 @@ TextBlock::TextBlock(const style::font &font, const QString &str, QFixed minResi
layout.beginLayout();
layout.createLine();
bool logCrashString = (rand_value<uchar>() % 4 == 1);
if (logCrashString) {
SignalHandlers::setCrashAnnotationRef("CrashString", &str);
}
BlockParser parser(&engine, this, minResizeWidth, _from, part);
if (logCrashString) {
SignalHandlers::clearCrashAnnotationRef("CrashString");
}
layout.endLayout();
}