From 9d3d16a7255f235fae36f0724886764748bc6c59 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 8 Feb 2021 02:10:30 +0300 Subject: [PATCH] Added initial ability to rotate and flip image to photo editor. --- Telegram/CMakeLists.txt | 1 + Telegram/SourceFiles/editor/photo_editor.cpp | 15 +++++++ Telegram/SourceFiles/editor/photo_editor.h | 4 ++ .../SourceFiles/editor/photo_editor_common.h | 17 ++++++++ .../editor/photo_editor_content.cpp | 39 ++++++++++++++----- .../SourceFiles/editor/photo_editor_content.h | 7 ++++ .../editor/photo_editor_controls.cpp | 9 +++++ .../editor/photo_editor_controls.h | 3 ++ 8 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 Telegram/SourceFiles/editor/photo_editor_common.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 0c8dbd271d..dde955df35 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -510,6 +510,7 @@ PRIVATE dialogs/dialogs_widget.h editor/photo_editor.cpp editor/photo_editor.h + editor/photo_editor_common.h editor/photo_editor_content.cpp editor/photo_editor_content.h editor/photo_editor_controls.cpp diff --git a/Telegram/SourceFiles/editor/photo_editor.cpp b/Telegram/SourceFiles/editor/photo_editor.cpp index 4f347ecdc6..270176eecb 100644 --- a/Telegram/SourceFiles/editor/photo_editor.cpp +++ b/Telegram/SourceFiles/editor/photo_editor.cpp @@ -29,6 +29,21 @@ PhotoEditor::PhotoEditor( - style::margins(0, contentRect.height(), 0, 0); _controls->setGeometry(controlsRect); }, lifetime()); + + _controls->rotateRequests( + ) | rpl::start_with_next([=](int angle) { + _modifications.angle += 90; + if (_modifications.angle >= 360) { + _modifications.angle -= 360; + } + _content->applyModifications(_modifications); + }, lifetime()); + + _controls->flipRequests( + ) | rpl::start_with_next([=] { + _modifications.flipped = !_modifications.flipped; + _content->applyModifications(_modifications); + }, lifetime()); } } // namespace Editor diff --git a/Telegram/SourceFiles/editor/photo_editor.h b/Telegram/SourceFiles/editor/photo_editor.h index 7cd0f04b51..ad07bf3906 100644 --- a/Telegram/SourceFiles/editor/photo_editor.h +++ b/Telegram/SourceFiles/editor/photo_editor.h @@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/rp_widget.h" +#include "editor/photo_editor_common.h" + #include "base/unique_qptr.h" namespace Editor { @@ -24,6 +26,8 @@ public: private: + PhotoModifications _modifications; + base::unique_qptr _content; base::unique_qptr _controls; diff --git a/Telegram/SourceFiles/editor/photo_editor_common.h b/Telegram/SourceFiles/editor/photo_editor_common.h new file mode 100644 index 0000000000..3a83db0c9d --- /dev/null +++ b/Telegram/SourceFiles/editor/photo_editor_common.h @@ -0,0 +1,17 @@ +/* +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 + +namespace Editor { + +struct PhotoModifications { + int angle = 0; + bool flipped = false; +}; + +} // namespace Editor diff --git a/Telegram/SourceFiles/editor/photo_editor_content.cpp b/Telegram/SourceFiles/editor/photo_editor_content.cpp index e63bd0a925..4b6f54bf47 100644 --- a/Telegram/SourceFiles/editor/photo_editor_content.cpp +++ b/Telegram/SourceFiles/editor/photo_editor_content.cpp @@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "editor/photo_editor_content.h" +#include "media/view/media_view_pip.h" + namespace Editor { PhotoEditorContent::PhotoEditorContent( @@ -14,23 +16,33 @@ PhotoEditorContent::PhotoEditorContent( std::shared_ptr photo) : RpWidget(parent) { - sizeValue( - ) | rpl::start_with_next([=](const QSize &size) { + rpl::combine( + _modifications.value(), + sizeValue() + ) | rpl::start_with_next([=]( + const PhotoModifications &mods, const QSize &size) { + const auto rotatedSize = + Media::View::FlipSizeByRotation(size, mods.angle); const auto imageSize = [&] { const auto originalSize = photo->size() / cIntRetinaFactor(); - if ((originalSize.width() > size.width()) - && (originalSize.height() > size.height())) { + if ((originalSize.width() > rotatedSize.width()) + || (originalSize.height() > rotatedSize.height())) { return originalSize.scaled( - size, + rotatedSize, Qt::KeepAspectRatio); } return originalSize; }(); _imageRect = QRect( - QPoint( - (size.width() - imageSize.width()) / 2, - (size.height() - imageSize.height()) / 2), + QPoint(-imageSize.width() / 2, -imageSize.height() / 2), imageSize); + + _imageMatrix.reset(); + _imageMatrix.translate(size.width() / 2, size.height() / 2); + if (mods.flipped) { + _imageMatrix.scale(-1, 1); + } + _imageMatrix.rotate(mods.angle); }, lifetime()); paintRequest( @@ -38,8 +50,17 @@ PhotoEditorContent::PhotoEditorContent( Painter p(this); p.fillRect(clip, Qt::transparent); - p.drawPixmap(_imageRect, *photo, photo->rect()); + + p.setMatrix(_imageMatrix); + + p.drawPixmap(_imageRect, *photo); }, lifetime()); } +void PhotoEditorContent::applyModifications( + PhotoModifications modifications) { + _modifications = std::move(modifications); + update(); +} + } // namespace Editor diff --git a/Telegram/SourceFiles/editor/photo_editor_content.h b/Telegram/SourceFiles/editor/photo_editor_content.h index e9424c3b60..e77fb9906a 100644 --- a/Telegram/SourceFiles/editor/photo_editor_content.h +++ b/Telegram/SourceFiles/editor/photo_editor_content.h @@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/rp_widget.h" +#include "editor/photo_editor_common.h" + namespace Editor { class PhotoEditorContent final : public Ui::RpWidget { @@ -17,9 +19,14 @@ public: not_null parent, std::shared_ptr photo); + void applyModifications(PhotoModifications modifications); + private: + rpl::variable _modifications; + QRect _imageRect; + QMatrix _imageMatrix; }; diff --git a/Telegram/SourceFiles/editor/photo_editor_controls.cpp b/Telegram/SourceFiles/editor/photo_editor_controls.cpp index d9de683f0e..79649e6a0e 100644 --- a/Telegram/SourceFiles/editor/photo_editor_controls.cpp +++ b/Telegram/SourceFiles/editor/photo_editor_controls.cpp @@ -75,4 +75,13 @@ PhotoEditorControls::PhotoEditorControls( }, lifetime()); } + +rpl::producer PhotoEditorControls::rotateRequests() const { + return _rotateButton->clicks() | rpl::map([] { return 90; }); +} + +rpl::producer<> PhotoEditorControls::flipRequests() const { + return _flipButton->clicks() | rpl::to_empty; +} + } // namespace Editor diff --git a/Telegram/SourceFiles/editor/photo_editor_controls.h b/Telegram/SourceFiles/editor/photo_editor_controls.h index a7f1f95b9e..59308b6c75 100644 --- a/Telegram/SourceFiles/editor/photo_editor_controls.h +++ b/Telegram/SourceFiles/editor/photo_editor_controls.h @@ -23,6 +23,9 @@ public: not_null parent, bool doneControls = true); + [[nodiscard]] rpl::producer rotateRequests() const; + [[nodiscard]] rpl::producer<> flipRequests() const; + private: const base::unique_qptr _buttonsContainer;