diff --git a/Telegram/SourceFiles/boxes/sticker_creator_box.cpp b/Telegram/SourceFiles/boxes/sticker_creator_box.cpp index a94ffdcfcc..5765a4b330 100644 --- a/Telegram/SourceFiles/boxes/sticker_creator_box.cpp +++ b/Telegram/SourceFiles/boxes/sticker_creator_box.cpp @@ -475,6 +475,7 @@ void OpenPhotoEditorForSticker( .exactSize = QSize(kStickerSide, kStickerSide), .cropType = Editor::EditorData::CropType::RoundedRect, .keepAspectRatio = true, + .fixedCrop = true, }); const auto raw = editor.get(); diff --git a/Telegram/SourceFiles/editor/editor_crop.cpp b/Telegram/SourceFiles/editor/editor_crop.cpp index 0fd553768f..df2e7422d7 100644 --- a/Telegram/SourceFiles/editor/editor_crop.cpp +++ b/Telegram/SourceFiles/editor/editor_crop.cpp @@ -177,6 +177,10 @@ void Crop::paintFrame(QPainter &p) { p.save(); p.setRenderHint(QPainter::Antialiasing, true); p.fillPath(frameShape, st::photoCropPointFg); + if (_data.fixedCrop) { + p.restore(); + return; + } { const auto cornerLength = std::min( float64(st::photoEditorCropPointSize * 2), @@ -286,6 +290,10 @@ void Crop::convertCropPaintToOriginal() { } void Crop::updateEdges() { + if (_data.fixedCrop) { + _edges.clear(); + return; + } const auto &s = _pointSize; const auto &m = _edgePointMargins; const auto &r = _cropPaint; @@ -338,6 +346,9 @@ Qt::Edges Crop::mouseState(const QPoint &p) { } void Crop::mousePressEvent(QMouseEvent *e) { + if (_data.fixedCrop) { + return; + } computeDownState(e->pos()); if (_down.edge) { setGridVisible(true, false); @@ -345,6 +356,9 @@ void Crop::mousePressEvent(QMouseEvent *e) { } void Crop::mouseReleaseEvent(QMouseEvent *e) { + if (_data.fixedCrop) { + return; + } const auto hadEdge = bool(_down.edge); if (hadEdge) { setGridVisible(false, true); @@ -474,6 +488,9 @@ void Crop::performMove(const QPoint &pos) { } void Crop::mouseMoveEvent(QMouseEvent *e) { + if (_data.fixedCrop) { + return; + } const auto pos = e->pos(); const auto pressedEdge = _down.edge; diff --git a/Telegram/SourceFiles/editor/photo_editor.cpp b/Telegram/SourceFiles/editor/photo_editor.cpp index 989ff8c40b..ac24d71a4d 100644 --- a/Telegram/SourceFiles/editor/photo_editor.cpp +++ b/Telegram/SourceFiles/editor/photo_editor.cpp @@ -237,6 +237,7 @@ PhotoEditor::PhotoEditor( std::move(show), _brushes, _brushTool)) { + _modifications.cropType = data.cropType; sizeValue( ) | rpl::on_next([=](const QSize &size) { diff --git a/Telegram/SourceFiles/editor/photo_editor_common.cpp b/Telegram/SourceFiles/editor/photo_editor_common.cpp index 4fd72ac829..cf95c04f43 100644 --- a/Telegram/SourceFiles/editor/photo_editor_common.cpp +++ b/Telegram/SourceFiles/editor/photo_editor_common.cpp @@ -9,8 +9,40 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "editor/scene/scene.h" #include "ui/painter.h" +#include "ui/userpic_view.h" namespace Editor { +namespace { + +void ApplyShapeMask(QImage &image, EditorData::CropType type) { + if (type == EditorData::CropType::Rect) { + return; + } + if (image.format() != QImage::Format_ARGB32_Premultiplied) { + image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + } + auto mask = QImage(image.size(), QImage::Format_ARGB32_Premultiplied); + mask.fill(Qt::transparent); + { + auto p = QPainter(&mask); + auto hq = PainterHighQualityEnabler(p); + p.setPen(Qt::NoPen); + p.setBrush(Qt::white); + const auto rect = QRectF(QPointF(), QSizeF(image.size())); + if (type == EditorData::CropType::Ellipse) { + p.drawEllipse(rect); + } else { + const auto radius = std::min(rect.width(), rect.height()) + * Ui::ForumUserpicRadiusMultiplier(); + p.drawRoundedRect(rect, radius, radius); + } + } + auto p = QPainter(&image); + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + p.drawImage(0, 0, mask); +} + +} // namespace QImage ImageModified(QImage image, const PhotoModifications &mods) { Expects(!image.isNull()); @@ -32,6 +64,7 @@ QImage ImageModified(QImage image, const PhotoModifications &mods) { auto cropped = mods.crop.isValid() ? image.copy(mods.crop) : image; + ApplyShapeMask(cropped, mods.cropType); QTransform transform; if (mods.flipped) { transform.scale(-1, 1); @@ -43,7 +76,11 @@ QImage ImageModified(QImage image, const PhotoModifications &mods) { } bool PhotoModifications::empty() const { - return !angle && !flipped && !crop.isValid() && !paint; + return !angle + && !flipped + && !crop.isValid() + && cropType == EditorData::CropType::Rect + && !paint; } PhotoModifications::operator bool() const { diff --git a/Telegram/SourceFiles/editor/photo_editor_common.h b/Telegram/SourceFiles/editor/photo_editor_common.h index b52b2110a7..55b11af658 100644 --- a/Telegram/SourceFiles/editor/photo_editor_common.h +++ b/Telegram/SourceFiles/editor/photo_editor_common.h @@ -11,18 +11,6 @@ namespace Editor { class Scene; -struct PhotoModifications { - int angle = 0; - bool flipped = false; - QRect crop; - std::shared_ptr paint = nullptr; - - [[nodiscard]] bool empty() const; - [[nodiscard]] explicit operator bool() const; - ~PhotoModifications(); - -}; - struct EditorData { enum class CropType { Rect, @@ -35,6 +23,20 @@ struct EditorData { QSize exactSize; CropType cropType = CropType::Rect; bool keepAspectRatio = false; + bool fixedCrop = false; +}; + +struct PhotoModifications { + int angle = 0; + bool flipped = false; + QRect crop; + EditorData::CropType cropType = EditorData::CropType::Rect; + std::shared_ptr paint = nullptr; + + [[nodiscard]] bool empty() const; + [[nodiscard]] explicit operator bool() const; + ~PhotoModifications(); + }; [[nodiscard]] QImage ImageModified(