diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index bf13c6159e..dd88a9e161 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -525,6 +525,8 @@ PRIVATE editor/photo_editor_layer_widget.h editor/scene_item_base.cpp editor/scene_item_base.h + editor/scene_item_sticker.cpp + editor/scene_item_sticker.h editor/stickers_panel_controller.cpp editor/stickers_panel_controller.h editor/undo_controller.cpp diff --git a/Telegram/SourceFiles/editor/editor.style b/Telegram/SourceFiles/editor/editor.style index bd6a89ac32..d4b362de4e 100644 --- a/Telegram/SourceFiles/editor/editor.style +++ b/Telegram/SourceFiles/editor/editor.style @@ -62,5 +62,7 @@ photoEditorCropPointSize: 10px; photoEditorCropMinSize: 20px; photoEditorItemHandleSize: 10px; -photoEditorItemMinSize: 16px; +photoEditorItemMinSize: 32px; photoEditorItemMaxSize: 512px; + +photoEditorItemStickerPadding: margins(5px, 5px, 5px, 5px); diff --git a/Telegram/SourceFiles/editor/editor_paint.cpp b/Telegram/SourceFiles/editor/editor_paint.cpp index b4a199cf75..ffdd975b9a 100644 --- a/Telegram/SourceFiles/editor/editor_paint.cpp +++ b/Telegram/SourceFiles/editor/editor_paint.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "editor/editor_paint.h" #include "editor/scene_item_base.h" +#include "editor/scene_item_sticker.h" #include "editor/controllers.h" #include "base/event_filter.h" @@ -45,6 +46,7 @@ Paint::Paint( const QSize &imageSize, std::shared_ptr controllers) : RpWidget(parent) +, _lastZ(std::make_shared(0.)) , _scene(EnsureScene(modifications)) , _view(base::make_unique_q(_scene.get(), this)) , _imageSize(imageSize) { @@ -100,6 +102,18 @@ Paint::Paint( controllers->stickersPanelController->setShowRequestChanges( controllers->stickersPanelController->stickerChosen( ) | rpl::map_to(std::optional(false))); + + controllers->stickersPanelController->stickerChosen( + ) | rpl::start_with_next([=](not_null document) { + const auto s = _scene->sceneRect().size(); + const auto size = std::min(s.width(), s.height()) / 2; + const auto x = s.width() / 2; + const auto y = s.height() / 2; + const auto item = new ItemSticker(document, _lastZ, size, x, y); + item->setZValue((*_lastZ)++); + _scene->addItem(item); + _scene->clearSelection(); + }, lifetime()); } } @@ -172,6 +186,7 @@ void Paint::initDrawing() { } std::shared_ptr Paint::saveScene() const { + _scene->clearSelection(); return _scene->items().empty() ? nullptr : ranges::none_of(_scene->items(), &QGraphicsItem::isVisible) diff --git a/Telegram/SourceFiles/editor/editor_paint.h b/Telegram/SourceFiles/editor/editor_paint.h index 9001e93dd8..0f1b8fbecb 100644 --- a/Telegram/SourceFiles/editor/editor_paint.h +++ b/Telegram/SourceFiles/editor/editor_paint.h @@ -53,6 +53,7 @@ private: std::vector groups( Qt::SortOrder order = Qt::DescendingOrder) const; + const std::shared_ptr _lastZ; const std::shared_ptr _scene; const base::unique_qptr _view; const QSize _imageSize; diff --git a/Telegram/SourceFiles/editor/scene_item_sticker.cpp b/Telegram/SourceFiles/editor/scene_item_sticker.cpp new file mode 100644 index 0000000000..0c8c2ea7dd --- /dev/null +++ b/Telegram/SourceFiles/editor/scene_item_sticker.cpp @@ -0,0 +1,88 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "editor/scene_item_sticker.h" + +#include "app.h" +#include "chat_helpers/stickers_lottie.h" +#include "data/data_document.h" +#include "data/data_document_media.h" +#include "data/data_session.h" +#include "lottie/lottie_common.h" +#include "lottie/lottie_single_player.h" +#include "main/main_session.h" +#include "styles/style_editor.h" + +namespace Editor { +namespace { + +} // namespace + +ItemSticker::ItemSticker( + not_null document, + std::shared_ptr zPtr, + int size, + int x, + int y) +: ItemBase(std::move(zPtr), size, x, y) +, _document(document) +, _mediaView(_document->createMediaView()) +, _thumbnailMargins(st::photoEditorItemStickerPadding) { + const auto stickerData = document->sticker(); + if (!stickerData) { + return; + } + const auto updateThumbnail = [=] { + if (stickerData->animated) { + _lottie.player = ChatHelpers::LottiePlayerFromDocument( + _mediaView.get(), + ChatHelpers::StickerLottieSize::MessageHistory, + QSize(kStickerSideSize, kStickerSideSize) + * cIntRetinaFactor(), + Lottie::Quality::High); + _lottie.player->updates( + ) | rpl::start_with_next([=] { + _pixmap = App::pixmapFromImageInPlace( + _lottie.player->frame()); + _lottie.player = nullptr; + _lottie.lifetime.destroy(); + update(); + }, _lottie.lifetime); + return true; + } + const auto sticker = _mediaView->getStickerLarge(); + if (!sticker) { + return false; + } + _pixmap = sticker->pixNoCache( + sticker->width() * cIntRetinaFactor(), + sticker->height() * cIntRetinaFactor(), + Images::Option::Smooth); + _pixmap.setDevicePixelRatio(cRetinaFactor()); + return true; + }; + if (!updateThumbnail()) { + _document->owner().session().downloaderTaskFinished( + ) | rpl::start_with_next([=] { + if (updateThumbnail()) { + _loadingLifetime.destroy(); + update(); + } + }, _loadingLifetime); + return; + } +} + +void ItemSticker::paint( + QPainter *p, + const QStyleOptionGraphicsItem *option, + QWidget *w) { + p->drawPixmap((innerRect() - _thumbnailMargins).toRect(), _pixmap); + ItemBase::paint(p, option, w); +} + +} // namespace Editor diff --git a/Telegram/SourceFiles/editor/scene_item_sticker.h b/Telegram/SourceFiles/editor/scene_item_sticker.h new file mode 100644 index 0000000000..213a957068 --- /dev/null +++ b/Telegram/SourceFiles/editor/scene_item_sticker.h @@ -0,0 +1,51 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "editor/scene_item_base.h" + +namespace Data { +class DocumentMedia; +} // namespace Data +namespace Lottie { +class SinglePlayer; +} // namespace Lottie +class DocumentData; + +namespace Editor { + +class ItemSticker : public ItemBase { +public: + enum { Type = ItemBase::Type + 1 }; + + ItemSticker( + not_null document, + std::shared_ptr zPtr, + int size, + int x, + int y); + void paint( + QPainter *p, + const QStyleOptionGraphicsItem *option, + QWidget *widget) override; +private: + const not_null _document; + const std::shared_ptr _mediaView; + const QMarginsF _thumbnailMargins; + + struct { + std::unique_ptr player; + rpl::lifetime lifetime; + } _lottie; + QPixmap _pixmap; + + rpl::lifetime _loadingLifetime; + +}; + +} // namespace Editor