diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 40817dc2e4..8a4ce9a126 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -950,7 +950,7 @@ namespace App { auto &d = size.c_photoSize(); if (d.vlocation.type() == mtpc_fileLocation) { auto &l = d.vlocation.c_fileLocation(); - return ImagePtr( + return Images::Create( StorageImageLocation( d.vw.v, d.vh.v, @@ -967,7 +967,7 @@ namespace App { if (d.vlocation.type() == mtpc_fileLocation) { auto &l = d.vlocation.c_fileLocation(); auto bytes = qba(d.vbytes); - return ImagePtr( + return Images::Create( StorageImageLocation( d.vw.v, d.vh.v, @@ -979,7 +979,7 @@ namespace App { bytes); } else if (d.vlocation.type() == mtpc_fileLocationUnavailable) { auto bytes = qba(d.vbytes); - return ImagePtr( + return Images::Create( StorageImageLocation( d.vw.v, d.vh.v, diff --git a/Telegram/SourceFiles/boxes/background_box.cpp b/Telegram/SourceFiles/boxes/background_box.cpp index f1381d2708..deb7c58110 100644 --- a/Telegram/SourceFiles/boxes/background_box.cpp +++ b/Telegram/SourceFiles/boxes/background_box.cpp @@ -94,7 +94,7 @@ BackgroundBox::Inner::Inner(QWidget *parent) : TWidget(parent) void BackgroundBox::Inner::gotWallpapers(const MTPVector &result) { App::WallPapers wallpapers; - auto oldBackground = ImagePtr(qsl(":/gui/art/bg_initial.jpg")); + auto oldBackground = Images::Create(qsl(":/gui/art/bg_initial.jpg"), "JPG"); wallpapers.push_back(App::WallPaper(Window::Theme::kInitialBackground, oldBackground, oldBackground)); auto &v = result.v; for_const (auto &w, v) { diff --git a/Telegram/SourceFiles/boxes/confirm_box.cpp b/Telegram/SourceFiles/boxes/confirm_box.cpp index 07b4a64d8c..0aa11bed47 100644 --- a/Telegram/SourceFiles/boxes/confirm_box.cpp +++ b/Telegram/SourceFiles/boxes/confirm_box.cpp @@ -679,7 +679,7 @@ ConfirmInviteBox::ConfirmInviteBox( size, data.vphoto_small); if (!location.isNull()) { - _photo = ImagePtr(location); + _photo = Images::Create(location); if (!_photo->loaded()) { subscribe(Auth().downloaderTaskFinished(), [this] { update(); }); _photo->load(Data::FileOrigin()); diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index 335923dcf3..e2011e4af9 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -661,7 +661,7 @@ bool DocumentData::loaded(FilePathResolveType type) const { that->_location = FileLocation(_loader->fileName()); that->_data = _loader->bytes(); if (that->sticker() && !_loader->imageData().isNull()) { - that->sticker()->img = ImagePtr(_data, _loader->imageFormat(), _loader->imageData()); + that->sticker()->img = Images::Create(_data, _loader->imageFormat(), _loader->imageData()); } destroyLoaderDelayed(); } @@ -954,7 +954,7 @@ ImagePtr DocumentData::makeReplyPreview(Data::FileOrigin origin) { auto options = Images::Option::Smooth | (isVideoMessage() ? Images::Option::Circled : Images::Option::None) | Images::Option::TransparentBackground; auto outerSize = st::msgReplyBarSize.height(); auto image = thumb->pixNoCache(origin, thumbSize.width(), thumbSize.height(), options, outerSize, outerSize); - replyPreview = ImagePtr(image.toImage(), "PNG"); + replyPreview = Images::Create(image.toImage(), "PNG"); } else { thumb->load(origin); } @@ -977,11 +977,11 @@ void DocumentData::checkSticker() { if (_data.isEmpty()) { const auto &loc = location(true); if (loc.accessEnable()) { - data->img = ImagePtr(loc.name()); + data->img = Images::Create(loc.name(), "WEBP"); loc.accessDisable(); } } else { - data->img = ImagePtr(_data); + data->img = Images::Create(_data, "WEBP"); } } } diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp index b25b0266d1..1a75a12be2 100644 --- a/Telegram/SourceFiles/data/data_media_types.cpp +++ b/Telegram/SourceFiles/data/data_media_types.cpp @@ -57,8 +57,7 @@ Invoice ComputeInvoiceData(const MTPDmessageMediaInvoice &data) { result.receiptMsgId = data.vreceipt_msg_id.v; } if (data.has_photo()) { - const auto thumb = ImagePtr(); - result.photo = Auth().data().photoFromWeb(data.vphoto, thumb); + result.photo = Auth().data().photoFromWeb(data.vphoto); } return result; } diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 2ef222cd68..f1ef81ec84 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -287,7 +287,7 @@ void PeerData::updateUserpic( const MTPFileLocation &location) { const auto size = kUserpicSize; const auto loc = StorageImageLocation::FromMTP(size, size, location); - const auto photo = loc.isNull() ? ImagePtr() : ImagePtr(loc); + const auto photo = loc.isNull() ? ImagePtr() : Images::Create(loc); setUserpicChecked(photoId, loc, photo); } @@ -301,7 +301,7 @@ void PeerData::clearUserpic() { Qt::SmoothTransformation); return _userpic ? _userpic - : ImagePtr(std::move(image), "PNG"); + : Images::Create(std::move(image), "PNG"); } return ImagePtr(); }(); diff --git a/Telegram/SourceFiles/data/data_photo.cpp b/Telegram/SourceFiles/data/data_photo.cpp index 41f6d116ed..2cb7896301 100644 --- a/Telegram/SourceFiles/data/data_photo.cpp +++ b/Telegram/SourceFiles/data/data_photo.cpp @@ -120,7 +120,7 @@ ImagePtr PhotoData::makeReplyPreview(Data::FileOrigin origin) { int w = image->width(), h = image->height(); if (w <= 0) w = 1; if (h <= 0) h = 1; - return ImagePtr( + return Images::Create( (w > h ? image->pix( origin, diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 71fd77eef4..32996d36f3 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -813,9 +813,9 @@ not_null Session::photo( data.c_photo().vaccess_hash.v, data.c_photo().vfile_reference.v, data.c_photo().vdate.v, - ImagePtr(base::duplicate(*thumb), "JPG"), - ImagePtr(base::duplicate(*medium), "JPG"), - ImagePtr(base::duplicate(*full), "JPG")); + Images::Create(base::duplicate(*thumb), "JPG"), + Images::Create(base::duplicate(*medium), "JPG"), + Images::Create(base::duplicate(*full), "JPG")); case mtpc_photoEmpty: return photo(data.c_photoEmpty().vid.v); @@ -875,20 +875,24 @@ void Session::photoConvert( PhotoData *Session::photoFromWeb( const MTPWebDocument &data, - ImagePtr thumb) { - const auto full = ImagePtr(data); + ImagePtr thumb, + bool willBecomeNormal) { + const auto full = Images::Create(data); if (full->isNull()) { return nullptr; } - //const auto width = full->width(); - //const auto height = full->height(); - //if (thumb->isNull()) { - // auto thumbsize = shrinkToKeepAspect(width, height, 100, 100); - // thumb = ImagePtr(thumbsize.width(), thumbsize.height()); - //} + auto medium = ImagePtr(); + if (willBecomeNormal) { + const auto width = full->width(); + const auto height = full->height(); + if (thumb->isNull()) { + auto thumbsize = shrinkToKeepAspect(width, height, 100, 100); + thumb = Images::Create(thumbsize.width(), thumbsize.height()); + } - //auto mediumsize = shrinkToKeepAspect(width, height, 320, 320); - //auto medium = ImagePtr(mediumsize.width(), mediumsize.height()); + auto mediumsize = shrinkToKeepAspect(width, height, 320, 320); + medium = Images::Create(mediumsize.width(), mediumsize.height()); + } return photo( rand_value(), @@ -896,7 +900,7 @@ PhotoData *Session::photoFromWeb( QByteArray(), unixtime(), thumb, - ImagePtr(), + medium, full); } @@ -911,7 +915,7 @@ void Session::photoApplyFields( void Session::photoApplyFields( not_null photo, const MTPDphoto &data) { - auto thumb = (const MTPPhotoSize*)nullptr; + auto thumb = (const MTPPhotoSize*)nullptr; auto medium = (const MTPPhotoSize*)nullptr; auto full = (const MTPPhotoSize*)nullptr; auto thumbLevel = -1; @@ -1027,7 +1031,7 @@ not_null Session::document( fields.vdate.v, fields.vattributes.v, qs(fields.vmime_type), - ImagePtr(std::move(thumb), "JPG"), + Images::Create(std::move(thumb), "JPG"), fields.vdc_id.v, fields.vsize.v, StorageImageLocation()); diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 62b60aa681..a3c3aa888c 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -262,7 +262,10 @@ public: void photoConvert( not_null original, const MTPPhoto &data); - PhotoData *photoFromWeb(const MTPWebDocument &data, ImagePtr thumb); + PhotoData *photoFromWeb( + const MTPWebDocument &data, + ImagePtr thumb = ImagePtr(), + bool willBecomeNormal = false); not_null document(DocumentId id); not_null document(const MTPDocument &data); diff --git a/Telegram/SourceFiles/history/history_location_manager.cpp b/Telegram/SourceFiles/history/history_location_manager.cpp index 81c8213399..d2fe73224c 100644 --- a/Telegram/SourceFiles/history/history_location_manager.cpp +++ b/Telegram/SourceFiles/history/history_location_manager.cpp @@ -57,7 +57,7 @@ void LocationClickHandler::setup() { LocationData::LocationData(const LocationCoords &coords) : coords(coords) -, thumb(ComputeLocation(coords)) { +, thumb(Images::Create(ComputeLocation(coords))) { } void LocationData::load(Data::FileOrigin origin) { diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp index affdd24fd0..bd0079941a 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp @@ -79,14 +79,15 @@ std::unique_ptr Result::create(uint64 queryId, const MTPBotInlineResult if (r.has_description()) result->_description = qs(r.vdescription); if (r.has_url()) result->_url = qs(r.vurl); if (r.has_thumb()) { - result->_thumb = ImagePtr(r.vthumb, result->thumbBox()); + result->_thumb = Images::Create(r.vthumb, result->thumbBox()); } if (r.has_content()) { result->_content_url = GetContentUrl(r.vcontent); if (result->_type == Type::Photo) { result->_photo = Auth().data().photoFromWeb( r.vcontent, - result->_thumb); + result->_thumb, + true); } else { result->_document = Auth().data().documentFromWeb( result->adjustAttributes(r.vcontent), @@ -237,7 +238,7 @@ std::unique_ptr Result::create(uint64 queryId, const MTPBotInlineResult location.height = h; location.zoom = zoom; location.scale = scale; - result->_locationThumb = ImagePtr(location); + result->_locationThumb = Images::Create(location); } return result; diff --git a/Telegram/SourceFiles/storage/serialize_common.cpp b/Telegram/SourceFiles/storage/serialize_common.cpp index 336ece341f..f207aeda15 100644 --- a/Telegram/SourceFiles/storage/serialize_common.cpp +++ b/Telegram/SourceFiles/storage/serialize_common.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/serialize_common.h" #include "auth_session.h" +#include "ui/image.h" namespace Serialize { @@ -255,7 +256,7 @@ PeerData *readPeer(int streamAppVersion, QDataStream &stream) { result->setUserpic( photoId, photoLoc, - photoLoc.isNull() ? ImagePtr() : ImagePtr(photoLoc)); + photoLoc.isNull() ? ImagePtr() : Images::Create(photoLoc)); } return result; } diff --git a/Telegram/SourceFiles/storage/serialize_document.cpp b/Telegram/SourceFiles/storage/serialize_document.cpp index 266aad55f1..9ccf36bdc4 100644 --- a/Telegram/SourceFiles/storage/serialize_document.cpp +++ b/Telegram/SourceFiles/storage/serialize_document.cpp @@ -137,7 +137,7 @@ DocumentData *Document::readFromStreamHelper(int streamAppVersion, QDataStream & date, attributes, mime, - thumb.isNull() ? ImagePtr() : ImagePtr(thumb), + thumb.isNull() ? ImagePtr() : Images::Create(thumb), dc, size, thumb); diff --git a/Telegram/SourceFiles/ui/image.cpp b/Telegram/SourceFiles/ui/image.cpp index 73f675043c..f3c2da7af3 100644 --- a/Telegram/SourceFiles/ui/image.cpp +++ b/Telegram/SourceFiles/ui/image.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history.h" #include "auth_session.h" +namespace Images { namespace { QMap LocalFileImages; @@ -35,8 +36,6 @@ uint64 SinglePixKey(Images::Options options) { } // namespace -namespace Images { - void ClearRemote() { for (auto image : base::take(StorageImages)) { delete image; @@ -68,6 +67,251 @@ void CheckCacheSize() { } } +ImagePtr Create(const QString &file, QByteArray format) { + if (file.startsWith(qstr("http://"), Qt::CaseInsensitive) + || file.startsWith(qstr("https://"), Qt::CaseInsensitive)) { + const auto key = file; + auto i = WebUrlImages.constFind(key); + if (i == WebUrlImages.cend()) { + i = WebUrlImages.insert( + key, + new Image(std::make_unique(file))); + } + return ImagePtr(i.value()); + } else { + QFileInfo f(file); + const auto key = qsl("//:%1//:%2//:" + ).arg(f.size() + ).arg(f.lastModified().toTime_t() + ) + file; + auto i = LocalFileImages.constFind(key); + if (i == LocalFileImages.cend()) { + i = LocalFileImages.insert( + key, + new Image(std::make_unique( + file, + QByteArray(), + format))); + } + return ImagePtr(i.value()); + } +} + +ImagePtr Create(const QString &url, QSize box) { + const auto key = qsl("//:%1//:%2//:").arg(box.width()).arg(box.height()) + url; + auto i = WebUrlImages.constFind(key); + if (i == WebUrlImages.cend()) { + i = WebUrlImages.insert( + key, + new Image(std::make_unique(url, box))); + } + return ImagePtr(i.value()); +} + +ImagePtr Create(const QString &url, int width, int height) { + const auto key = url; + auto i = WebUrlImages.constFind(key); + if (i == WebUrlImages.cend()) { + i = WebUrlImages.insert( + key, + new Image(std::make_unique(url, width, height))); + } else { + i.value()->setInformation(0, width, height); + } + return ImagePtr(i.value()); +} + +ImagePtr Create(const QByteArray &filecontent, QByteArray format) { + auto image = App::readImage(filecontent, &format, false); + return Create(filecontent, format, std::move(image)); +} + +ImagePtr Create(QImage &&image, QByteArray format) { + return ImagePtr(new Image(std::make_unique( + std::move(image), + format))); +} + +ImagePtr Create( + const QByteArray &filecontent, + QByteArray format, + QImage &&image) { + return ImagePtr(new Image(std::make_unique( + QString(), + filecontent, + format, + std::move(image)))); +} + +ImagePtr Create(int width, int height) { + return ImagePtr(new Image(std::make_unique( + width, + height))); +} + +ImagePtr Create(const StorageImageLocation &location, int size) { + const auto key = storageKey(location); + auto i = StorageImages.constFind(key); + if (i == StorageImages.cend()) { + i = StorageImages.insert( + key, + new Image(std::make_unique(location, size))); + } else { + i.value()->refreshFileReference(location.fileReference()); + } + return ImagePtr(i.value()); +} + +ImagePtr Create( + const StorageImageLocation &location, + const QByteArray &bytes) { + const auto key = storageKey(location); + auto i = StorageImages.constFind(key); + if (i == StorageImages.cend()) { + i = StorageImages.insert( + key, + new Image(std::make_unique( + location, + bytes.size()))); + } else { + i.value()->refreshFileReference(location.fileReference()); + } + i.value()->setImageBytes(bytes); + return ImagePtr(i.value()); +} + +QSize getImageSize(const QVector &attributes) { + for (const auto &attribute : attributes) { + if (attribute.type() == mtpc_documentAttributeImageSize) { + auto &size = attribute.c_documentAttributeImageSize(); + return QSize(size.vw.v, size.vh.v); + } + } + return QSize(); +} + +ImagePtr Create(const MTPDwebDocument &document) { + const auto size = getImageSize(document.vattributes.v); + if (size.isEmpty()) { + return Image::Blank(); + } + + // We don't use size from WebDocument, because it is not reliable. + // It can be > 0 and different from the real size that we get in upload.WebFile result. + auto filesize = 0; // document.vsize.v; + return Create( + WebFileLocation( + Global::WebFileDcId(), + document.vurl.v, + document.vaccess_hash.v), + size.width(), + size.height(), + filesize); +} + +ImagePtr Create(const MTPDwebDocumentNoProxy &document) { + const auto size = getImageSize(document.vattributes.v); + if (size.isEmpty()) { + return Image::Blank(); + } + + return Create(qs(document.vurl), size.width(), size.height()); +} + +ImagePtr Create(const MTPDwebDocument &document, QSize box) { + //const auto size = getImageSize(document.vattributes.v); + //if (size.isEmpty()) { + // return Image::Blank(); + //} + + // We don't use size from WebDocument, because it is not reliable. + // It can be > 0 and different from the real size that we get in upload.WebFile result. + auto filesize = 0; // document.vsize.v; + return Create( + WebFileLocation( + Global::WebFileDcId(), + document.vurl.v, + document.vaccess_hash.v), + box, + filesize); +} + +ImagePtr Create(const MTPDwebDocumentNoProxy &document, QSize box) { + //const auto size = getImageSize(document.vattributes.v); + //if (size.isEmpty()) { + // return Image::Blank(); + //} + + return Create(qs(document.vurl), box); +} + +ImagePtr Create(const MTPWebDocument &document) { + switch (document.type()) { + case mtpc_webDocument: + return Create(document.c_webDocument()); + case mtpc_webDocumentNoProxy: + return Create(document.c_webDocumentNoProxy()); + } + Unexpected("Type in getImage(MTPWebDocument)."); +} + +ImagePtr Create(const MTPWebDocument &document, QSize box) { + switch (document.type()) { + case mtpc_webDocument: + return Create(document.c_webDocument(), box); + case mtpc_webDocumentNoProxy: + return Create(document.c_webDocumentNoProxy(), box); + } + Unexpected("Type in getImage(MTPWebDocument)."); +} + +ImagePtr Create( + const WebFileLocation &location, + QSize box, + int size) { + const auto key = storageKey(location); + auto i = WebCachedImages.constFind(key); + if (i == WebCachedImages.cend()) { + i = WebCachedImages.insert( + key, + new Image(std::make_unique( + location, + box, + size))); + } + return ImagePtr(i.value()); +} + +ImagePtr Create( + const WebFileLocation &location, + int width, + int height, + int size) { + const auto key = storageKey(location); + auto i = WebCachedImages.constFind(key); + if (i == WebCachedImages.cend()) { + i = WebCachedImages.insert( + key, + new Image(std::make_unique( + location, + width, + height, + size))); + } + return ImagePtr(i.value()); +} + +ImagePtr Create(const GeoPointLocation &location) { + const auto key = storageKey(location); + auto i = GeoPointImages.constFind(key); + if (i == GeoPointImages.cend()) { + i = GeoPointImages.insert( + key, + new Image(std::make_unique(location))); + } + return ImagePtr(i.value()); +} + Source::~Source() = default; ImageSource::ImageSource(QImage &&data, const QByteArray &format) @@ -782,7 +1026,7 @@ void Image::replaceSource(std::unique_ptr &&source) { _source = std::move(source); } -Image *Image::Blank() { +ImagePtr Image::Blank() { static const auto blankImage = [] { const auto factor = cIntRetinaFactor(); auto data = QImage( @@ -791,7 +1035,7 @@ Image *Image::Blank() { QImage::Format_ARGB32_Premultiplied); data.fill(Qt::transparent); data.setDevicePixelRatio(cRetinaFactor()); - return Images::details::Create( + return Images::Create( std::move(data), "GIF"); }(); @@ -799,7 +1043,7 @@ Image *Image::Blank() { } bool Image::isNull() const { - return (this == Blank()); + return (this == Blank().get()); } const QPixmap &Image::pix( @@ -815,14 +1059,14 @@ const QPixmap &Image::pix( h *= cIntRetinaFactor(); } auto options = Images::Option::Smooth | Images::Option::None; - auto k = PixKey(w, h, options); + auto k = Images::PixKey(w, h, options); auto i = _sizesCache.constFind(k); if (i == _sizesCache.cend()) { auto p = pixNoCache(origin, w, h, options); p.setDevicePixelRatio(cRetinaFactor()); i = _sizesCache.insert(k, p); if (!p.isNull()) { - GlobalAcquiredSize += int64(p.width()) * p.height() * 4; + Images::GlobalAcquiredSize += int64(p.width()) * p.height() * 4; } } return i.value(); @@ -856,14 +1100,14 @@ const QPixmap &Image::pixRounded( } else if (radius == ImageRoundRadius::Ellipse) { options |= Images::Option::Circled | cornerOptions(corners); } - auto k = PixKey(w, h, options); + auto k = Images::PixKey(w, h, options); auto i = _sizesCache.constFind(k); if (i == _sizesCache.cend()) { auto p = pixNoCache(origin, w, h, options); p.setDevicePixelRatio(cRetinaFactor()); i = _sizesCache.insert(k, p); if (!p.isNull()) { - GlobalAcquiredSize += int64(p.width()) * p.height() * 4; + Images::GlobalAcquiredSize += int64(p.width()) * p.height() * 4; } } return i.value(); @@ -882,14 +1126,14 @@ const QPixmap &Image::pixCircled( h *= cIntRetinaFactor(); } auto options = Images::Option::Smooth | Images::Option::Circled; - auto k = PixKey(w, h, options); + auto k = Images::PixKey(w, h, options); auto i = _sizesCache.constFind(k); if (i == _sizesCache.cend()) { auto p = pixNoCache(origin, w, h, options); p.setDevicePixelRatio(cRetinaFactor()); i = _sizesCache.insert(k, p); if (!p.isNull()) { - GlobalAcquiredSize += int64(p.width()) * p.height() * 4; + Images::GlobalAcquiredSize += int64(p.width()) * p.height() * 4; } } return i.value(); @@ -908,14 +1152,14 @@ const QPixmap &Image::pixBlurredCircled( h *= cIntRetinaFactor(); } auto options = Images::Option::Smooth | Images::Option::Circled | Images::Option::Blurred; - auto k = PixKey(w, h, options); + auto k = Images::PixKey(w, h, options); auto i = _sizesCache.constFind(k); if (i == _sizesCache.cend()) { auto p = pixNoCache(origin, w, h, options); p.setDevicePixelRatio(cRetinaFactor()); i = _sizesCache.insert(k, p); if (!p.isNull()) { - GlobalAcquiredSize += int64(p.width()) * p.height() * 4; + Images::GlobalAcquiredSize += int64(p.width()) * p.height() * 4; } } return i.value(); @@ -934,14 +1178,14 @@ const QPixmap &Image::pixBlurred( h *= cIntRetinaFactor(); } auto options = Images::Option::Smooth | Images::Option::Blurred; - auto k = PixKey(w, h, options); + auto k = Images::PixKey(w, h, options); auto i = _sizesCache.constFind(k); if (i == _sizesCache.cend()) { auto p = pixNoCache(origin, w, h, options); p.setDevicePixelRatio(cRetinaFactor()); i = _sizesCache.insert(k, p); if (!p.isNull()) { - GlobalAcquiredSize += int64(p.width()) * p.height() * 4; + Images::GlobalAcquiredSize += int64(p.width()) * p.height() * 4; } } return i.value(); @@ -961,14 +1205,14 @@ const QPixmap &Image::pixColored( h *= cIntRetinaFactor(); } auto options = Images::Option::Smooth | Images::Option::Colored; - auto k = PixKey(w, h, options); + auto k = Images::PixKey(w, h, options); auto i = _sizesCache.constFind(k); if (i == _sizesCache.cend()) { auto p = pixColoredNoCache(origin, add, w, h, true); p.setDevicePixelRatio(cRetinaFactor()); i = _sizesCache.insert(k, p); if (!p.isNull()) { - GlobalAcquiredSize += int64(p.width()) * p.height() * 4; + Images::GlobalAcquiredSize += int64(p.width()) * p.height() * 4; } } return i.value(); @@ -988,14 +1232,14 @@ const QPixmap &Image::pixBlurredColored( h *= cIntRetinaFactor(); } auto options = Images::Option::Blurred | Images::Option::Smooth | Images::Option::Colored; - auto k = PixKey(w, h, options); + auto k = Images::PixKey(w, h, options); auto i = _sizesCache.constFind(k); if (i == _sizesCache.cend()) { auto p = pixBlurredColoredNoCache(origin, add, w, h); p.setDevicePixelRatio(cRetinaFactor()); i = _sizesCache.insert(k, p); if (!p.isNull()) { - GlobalAcquiredSize += int64(p.width()) * p.height() * 4; + Images::GlobalAcquiredSize += int64(p.width()) * p.height() * 4; } } return i.value(); @@ -1037,17 +1281,17 @@ const QPixmap &Image::pixSingle( options |= Images::Option::Colored; } - auto k = SinglePixKey(options); + auto k = Images::SinglePixKey(options); auto i = _sizesCache.constFind(k); if (i == _sizesCache.cend() || i->width() != (outerw * cIntRetinaFactor()) || i->height() != (outerh * cIntRetinaFactor())) { if (i != _sizesCache.cend()) { - GlobalAcquiredSize -= int64(i->width()) * i->height() * 4; + Images::GlobalAcquiredSize -= int64(i->width()) * i->height() * 4; } auto p = pixNoCache(origin, w, h, options, outerw, outerh, colored); p.setDevicePixelRatio(cRetinaFactor()); i = _sizesCache.insert(k, p); if (!p.isNull()) { - GlobalAcquiredSize += int64(p.width()) * p.height() * 4; + Images::GlobalAcquiredSize += int64(p.width()) * p.height() * 4; } } return i.value(); @@ -1085,17 +1329,17 @@ const QPixmap &Image::pixBlurredSingle( options |= Images::Option::Circled | cornerOptions(corners); } - auto k = SinglePixKey(options); + auto k = Images::SinglePixKey(options); auto i = _sizesCache.constFind(k); if (i == _sizesCache.cend() || i->width() != (outerw * cIntRetinaFactor()) || i->height() != (outerh * cIntRetinaFactor())) { if (i != _sizesCache.cend()) { - GlobalAcquiredSize -= int64(i->width()) * i->height() * 4; + Images::GlobalAcquiredSize -= int64(i->width()) * i->height() * 4; } auto p = pixNoCache(origin, w, h, options, outerw, outerh); p.setDevicePixelRatio(cRetinaFactor()); i = _sizesCache.insert(k, p); if (!p.isNull()) { - GlobalAcquiredSize += int64(p.width()) * p.height() * 4; + Images::GlobalAcquiredSize += int64(p.width()) * p.height() * 4; } } return i.value(); @@ -1228,7 +1472,7 @@ void Image::checkSource() const { invalidateSizeCache(); _data = std::move(data); if (!_data.isNull()) { - GlobalAcquiredSize += int64(_data.width()) * _data.height() * 4; + Images::GlobalAcquiredSize += int64(_data.width()) * _data.height() * 4; } } } @@ -1238,7 +1482,7 @@ void Image::forget() const { _source->forget(); invalidateSizeCache(); if (!_data.isNull()) { - GlobalAcquiredSize -= int64(_data.width()) * _data.height() * 4; + Images::GlobalAcquiredSize -= int64(_data.width()) * _data.height() * 4; _data = QImage(); } } @@ -1260,7 +1504,7 @@ void Image::setImageBytes(const QByteArray &bytes) { void Image::invalidateSizeCache() const { for (const auto &image : std::as_const(_sizesCache)) { if (!image.isNull()) { - GlobalAcquiredSize -= int64(image.width()) * image.height() * 4; + Images::GlobalAcquiredSize -= int64(image.width()) * image.height() * 4; } } _sizesCache.clear(); @@ -1269,252 +1513,3 @@ void Image::invalidateSizeCache() const { Image::~Image() { forget(); } - -namespace Images { -namespace details { - -Image *Create(const QString &file, QByteArray format) { - if (file.startsWith(qstr("http://"), Qt::CaseInsensitive) - || file.startsWith(qstr("https://"), Qt::CaseInsensitive)) { - const auto key = file; - auto i = WebUrlImages.constFind(key); - if (i == WebUrlImages.cend()) { - i = WebUrlImages.insert( - key, - new Image(std::make_unique(file))); - } - return i.value(); - } else { - QFileInfo f(file); - const auto key = qsl("//:%1//:%2//:" - ).arg(f.size() - ).arg(f.lastModified().toTime_t() - ) + file; - auto i = LocalFileImages.constFind(key); - if (i == LocalFileImages.cend()) { - i = LocalFileImages.insert( - key, - new Image(std::make_unique( - file, - QByteArray(), - format))); - } - return i.value(); - } -} - -Image *Create(const QString &url, QSize box) { - const auto key = qsl("//:%1//:%2//:").arg(box.width()).arg(box.height()) + url; - auto i = WebUrlImages.constFind(key); - if (i == WebUrlImages.cend()) { - i = WebUrlImages.insert( - key, - new Image(std::make_unique(url, box))); - } - return i.value(); -} - -Image *Create(const QString &url, int width, int height) { - const auto key = url; - auto i = WebUrlImages.constFind(key); - if (i == WebUrlImages.cend()) { - i = WebUrlImages.insert( - key, - new Image(std::make_unique(url, width, height))); - } else { - i.value()->setInformation(0, width, height); - } - return i.value(); -} - -Image *Create(const QByteArray &filecontent, QByteArray format) { - auto image = App::readImage(filecontent, &format, false); - return Create(filecontent, format, std::move(image)); -} - -Image *Create(QImage &&image, QByteArray format) { - return new Image(std::make_unique( - std::move(image), - format)); -} - -Image *Create( - const QByteArray &filecontent, - QByteArray format, - QImage &&image) { - return new Image(std::make_unique( - QString(), - filecontent, - format, - std::move(image))); -} - -Image *Create(int width, int height) { - return new Image(std::make_unique(width, height)); -} - -Image *Create(const StorageImageLocation &location, int size) { - const auto key = storageKey(location); - auto i = StorageImages.constFind(key); - if (i == StorageImages.cend()) { - i = StorageImages.insert( - key, - new Image(std::make_unique(location, size))); - } else { - i.value()->refreshFileReference(location.fileReference()); - } - return i.value(); -} - -Image *Create( - const StorageImageLocation &location, - const QByteArray &bytes) { - const auto key = storageKey(location); - auto i = StorageImages.constFind(key); - if (i == StorageImages.cend()) { - i = StorageImages.insert( - key, - new Image(std::make_unique( - location, - bytes.size()))); - } else { - i.value()->refreshFileReference(location.fileReference()); - } - i.value()->setImageBytes(bytes); - return i.value(); -} - -QSize getImageSize(const QVector &attributes) { - for (const auto &attribute : attributes) { - if (attribute.type() == mtpc_documentAttributeImageSize) { - auto &size = attribute.c_documentAttributeImageSize(); - return QSize(size.vw.v, size.vh.v); - } - } - return QSize(); -} - -Image *Create(const MTPDwebDocument &document) { - const auto size = getImageSize(document.vattributes.v); - if (size.isEmpty()) { - return Image::Blank(); - } - - // We don't use size from WebDocument, because it is not reliable. - // It can be > 0 and different from the real size that we get in upload.WebFile result. - auto filesize = 0; // document.vsize.v; - return Create( - WebFileLocation( - Global::WebFileDcId(), - document.vurl.v, - document.vaccess_hash.v), - size.width(), - size.height(), - filesize); -} - -Image *Create(const MTPDwebDocumentNoProxy &document) { - const auto size = getImageSize(document.vattributes.v); - if (size.isEmpty()) { - return Image::Blank(); - } - - return Create(qs(document.vurl), size.width(), size.height()); -} - -Image *Create(const MTPDwebDocument &document, QSize box) { - //const auto size = getImageSize(document.vattributes.v); - //if (size.isEmpty()) { - // return Image::Blank(); - //} - - // We don't use size from WebDocument, because it is not reliable. - // It can be > 0 and different from the real size that we get in upload.WebFile result. - auto filesize = 0; // document.vsize.v; - return Create( - WebFileLocation( - Global::WebFileDcId(), - document.vurl.v, - document.vaccess_hash.v), - box, - filesize); -} - -Image *Create(const MTPDwebDocumentNoProxy &document, QSize box) { - //const auto size = getImageSize(document.vattributes.v); - //if (size.isEmpty()) { - // return Image::Blank(); - //} - - return Create(qs(document.vurl), box); -} - -Image *Create(const MTPWebDocument &document) { - switch (document.type()) { - case mtpc_webDocument: - return Create(document.c_webDocument()); - case mtpc_webDocumentNoProxy: - return Create(document.c_webDocumentNoProxy()); - } - Unexpected("Type in getImage(MTPWebDocument)."); -} - -Image *Create(const MTPWebDocument &document, QSize box) { - switch (document.type()) { - case mtpc_webDocument: - return Create(document.c_webDocument(), box); - case mtpc_webDocumentNoProxy: - return Create(document.c_webDocumentNoProxy(), box); - } - Unexpected("Type in getImage(MTPWebDocument)."); -} - -Image *Create( - const WebFileLocation &location, - QSize box, - int size) { - const auto key = storageKey(location); - auto i = WebCachedImages.constFind(key); - if (i == WebCachedImages.cend()) { - i = WebCachedImages.insert( - key, - new Image(std::make_unique( - location, - box, - size))); - } - return i.value(); -} - -Image *Create( - const WebFileLocation &location, - int width, - int height, - int size) { - const auto key = storageKey(location); - auto i = WebCachedImages.constFind(key); - if (i == WebCachedImages.cend()) { - i = WebCachedImages.insert( - key, - new Image(std::make_unique( - location, - width, - height, - size))); - } - return i.value(); -} - -Image *Create(const GeoPointLocation &location) { - const auto key = storageKey(location); - auto i = GeoPointImages.constFind(key); - if (i == GeoPointImages.cend()) { - i = GeoPointImages.insert( - key, - new Image(std::make_unique(location))); - } - return i.value(); -} - -} // namespace detals -} // namespace Images diff --git a/Telegram/SourceFiles/ui/image.h b/Telegram/SourceFiles/ui/image.h index af943770c1..d79f472cff 100644 --- a/Telegram/SourceFiles/ui/image.h +++ b/Telegram/SourceFiles/ui/image.h @@ -13,6 +13,33 @@ void ClearRemote(); void ClearAll(); void CheckCacheSize(); +ImagePtr Create(const QString &file, QByteArray format); +ImagePtr Create(const QString &url, QSize box); +ImagePtr Create(const QString &url, int width, int height); +ImagePtr Create(const QByteArray &filecontent, QByteArray format); +ImagePtr Create(QImage &&data, QByteArray format); +ImagePtr Create( + const QByteArray &filecontent, + QByteArray format, + QImage &&data); +ImagePtr Create(int width, int height); +ImagePtr Create(const StorageImageLocation &location, int size = 0); +ImagePtr Create( // photoCachedSize + const StorageImageLocation &location, + const QByteArray &bytes); +ImagePtr Create(const MTPWebDocument &location); +ImagePtr Create(const MTPWebDocument &location, QSize box); +ImagePtr Create( + const WebFileLocation &location, + int width, + int height, + int size = 0); +ImagePtr Create( + const WebFileLocation &location, + QSize box, + int size = 0); +ImagePtr Create(const GeoPointLocation &location); + class Source { public: virtual ~Source(); @@ -370,7 +397,7 @@ public: void replaceSource(std::unique_ptr &&source); - static Image *Blank(); + static ImagePtr Blank(); const QPixmap &pix( Data::FileOrigin origin, @@ -522,37 +549,3 @@ private: mutable QImage _data; }; - -namespace Images { -namespace details { - -Image *Create(const QString &file, QByteArray format); -Image *Create(const QString &url, QSize box); -Image *Create(const QString &url, int width, int height); -Image *Create(const QByteArray &filecontent, QByteArray format); -Image *Create(QImage &&data, QByteArray format); -Image *Create( - const QByteArray &filecontent, - QByteArray format, - QImage &&data); -Image *Create(int width, int height); -Image *Create(const StorageImageLocation &location, int size = 0); -Image *Create( // photoCachedSize - const StorageImageLocation &location, - const QByteArray &bytes); -Image *Create(const MTPWebDocument &location); -Image *Create(const MTPWebDocument &location, QSize box); -Image *Create( - const WebFileLocation &location, - int width, - int height, - int size = 0); -Image *Create( - const WebFileLocation &location, - QSize box, - int size = 0); -Image *Create( - const GeoPointLocation &location); - -} // namespace details -} // namespace Images diff --git a/Telegram/SourceFiles/ui/images.cpp b/Telegram/SourceFiles/ui/images.cpp index d203aa2a66..66be050d10 100644 --- a/Telegram/SourceFiles/ui/images.cpp +++ b/Telegram/SourceFiles/ui/images.cpp @@ -367,83 +367,10 @@ QImage prepare(QImage img, int w, int h, Images::Options options, int outerw, in } // namespace Images -ImagePtr::ImagePtr() : _data(Image::Blank()) { +ImagePtr::ImagePtr() : _data(Image::Blank().get()) { } -ImagePtr::ImagePtr(const QString &file, QByteArray format) -: _data(Images::details::Create(file, format)) { -} - -ImagePtr::ImagePtr(const QString &url, QSize box) -: _data(Images::details::Create(url, box)) { -} - -ImagePtr::ImagePtr(const QString &url, int width, int height) -: _data(Images::details::Create(url, width, height)) { -} - -ImagePtr::ImagePtr(const QByteArray &filecontent, QByteArray format) -: _data(Images::details::Create(filecontent, format)) { -} - -ImagePtr::ImagePtr( - const QByteArray &filecontent, - QByteArray format, - QImage &&data) -: _data(Images::details::Create(filecontent, format, std::move(data))) { -} - -ImagePtr::ImagePtr(QImage &&data, QByteArray format) -: _data(Images::details::Create(std::move(data), format)) { -} - -ImagePtr::ImagePtr(const StorageImageLocation &location, int32 size) -: _data(Images::details::Create(location, size)) { -} - -ImagePtr::ImagePtr( - const StorageImageLocation &location, - const QByteArray &bytes) -: _data(Images::details::Create(location, bytes)) { -} - -ImagePtr::ImagePtr(const MTPWebDocument &location) -: _data(Images::details::Create(location)) { -} - -ImagePtr::ImagePtr(const MTPWebDocument &location, QSize box) -: _data(Images::details::Create(location, box)) { -} - -ImagePtr::ImagePtr( - const WebFileLocation &location, - int width, - int height, - int size) -: _data(Images::details::Create(location, width, height, size)) { -} - -ImagePtr::ImagePtr(const WebFileLocation &location, QSize box, int size) -: _data(Images::details::Create(location, box, size)) { -} - -ImagePtr::ImagePtr(const GeoPointLocation &location) -: _data(Images::details::Create(location)) { -} - -ImagePtr::ImagePtr( - int32 width, - int32 height, - const MTPFileLocation &location, - ImagePtr def) -: _data((location.type() != mtpc_fileLocation) - ? def.get() - : (Image*)(Images::details::Create( - StorageImageLocation(width, height, location.c_fileLocation())))) { -} - -ImagePtr::ImagePtr(int32 width, int32 height) -: _data(Images::details::Create(width, height)) { +ImagePtr::ImagePtr(not_null data) : _data(data) { } Image *ImagePtr::operator->() const { diff --git a/Telegram/SourceFiles/ui/images.h b/Telegram/SourceFiles/ui/images.h index a420be3e36..93238c32d9 100644 --- a/Telegram/SourceFiles/ui/images.h +++ b/Telegram/SourceFiles/ui/images.h @@ -283,21 +283,7 @@ class Image; class ImagePtr { public: ImagePtr(); - ImagePtr(const QString &file, QByteArray format = QByteArray()); - ImagePtr(const QString &url, QSize box); - ImagePtr(const QString &url, int width, int height); - ImagePtr(const QByteArray &filecontent, QByteArray format = QByteArray()); - ImagePtr(const QByteArray &filecontent, QByteArray format, QImage &&data); - ImagePtr(QImage &&data, QByteArray format); - ImagePtr(const StorageImageLocation &location, int32 size = 0); - ImagePtr(const StorageImageLocation &location, const QByteArray &bytes); - ImagePtr(const MTPWebDocument &location); - ImagePtr(const MTPWebDocument &location, QSize box); - ImagePtr(const WebFileLocation &location, int width, int height, int size = 0); - ImagePtr(const WebFileLocation &location, QSize box, int size = 0); - ImagePtr(const GeoPointLocation &location); - ImagePtr(int32 width, int32 height, const MTPFileLocation &location, ImagePtr def = ImagePtr()); - ImagePtr(int32 width, int32 height); + explicit ImagePtr(not_null data); Image *operator->() const; Image *get() const;