mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
[img-editor] Locked crop frame as stencil and clipped output by shape.
This commit is contained in:
@@ -475,6 +475,7 @@ void OpenPhotoEditorForSticker(
|
|||||||
.exactSize = QSize(kStickerSide, kStickerSide),
|
.exactSize = QSize(kStickerSide, kStickerSide),
|
||||||
.cropType = Editor::EditorData::CropType::RoundedRect,
|
.cropType = Editor::EditorData::CropType::RoundedRect,
|
||||||
.keepAspectRatio = true,
|
.keepAspectRatio = true,
|
||||||
|
.fixedCrop = true,
|
||||||
});
|
});
|
||||||
const auto raw = editor.get();
|
const auto raw = editor.get();
|
||||||
|
|
||||||
|
|||||||
@@ -177,6 +177,10 @@ void Crop::paintFrame(QPainter &p) {
|
|||||||
p.save();
|
p.save();
|
||||||
p.setRenderHint(QPainter::Antialiasing, true);
|
p.setRenderHint(QPainter::Antialiasing, true);
|
||||||
p.fillPath(frameShape, st::photoCropPointFg);
|
p.fillPath(frameShape, st::photoCropPointFg);
|
||||||
|
if (_data.fixedCrop) {
|
||||||
|
p.restore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
{
|
{
|
||||||
const auto cornerLength = std::min(
|
const auto cornerLength = std::min(
|
||||||
float64(st::photoEditorCropPointSize * 2),
|
float64(st::photoEditorCropPointSize * 2),
|
||||||
@@ -286,6 +290,10 @@ void Crop::convertCropPaintToOriginal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Crop::updateEdges() {
|
void Crop::updateEdges() {
|
||||||
|
if (_data.fixedCrop) {
|
||||||
|
_edges.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto &s = _pointSize;
|
const auto &s = _pointSize;
|
||||||
const auto &m = _edgePointMargins;
|
const auto &m = _edgePointMargins;
|
||||||
const auto &r = _cropPaint;
|
const auto &r = _cropPaint;
|
||||||
@@ -338,6 +346,9 @@ Qt::Edges Crop::mouseState(const QPoint &p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Crop::mousePressEvent(QMouseEvent *e) {
|
void Crop::mousePressEvent(QMouseEvent *e) {
|
||||||
|
if (_data.fixedCrop) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
computeDownState(e->pos());
|
computeDownState(e->pos());
|
||||||
if (_down.edge) {
|
if (_down.edge) {
|
||||||
setGridVisible(true, false);
|
setGridVisible(true, false);
|
||||||
@@ -345,6 +356,9 @@ void Crop::mousePressEvent(QMouseEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Crop::mouseReleaseEvent(QMouseEvent *e) {
|
void Crop::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
|
if (_data.fixedCrop) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto hadEdge = bool(_down.edge);
|
const auto hadEdge = bool(_down.edge);
|
||||||
if (hadEdge) {
|
if (hadEdge) {
|
||||||
setGridVisible(false, true);
|
setGridVisible(false, true);
|
||||||
@@ -474,6 +488,9 @@ void Crop::performMove(const QPoint &pos) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Crop::mouseMoveEvent(QMouseEvent *e) {
|
void Crop::mouseMoveEvent(QMouseEvent *e) {
|
||||||
|
if (_data.fixedCrop) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto pos = e->pos();
|
const auto pos = e->pos();
|
||||||
const auto pressedEdge = _down.edge;
|
const auto pressedEdge = _down.edge;
|
||||||
|
|
||||||
|
|||||||
@@ -237,6 +237,7 @@ PhotoEditor::PhotoEditor(
|
|||||||
std::move(show),
|
std::move(show),
|
||||||
_brushes,
|
_brushes,
|
||||||
_brushTool)) {
|
_brushTool)) {
|
||||||
|
_modifications.cropType = data.cropType;
|
||||||
|
|
||||||
sizeValue(
|
sizeValue(
|
||||||
) | rpl::on_next([=](const QSize &size) {
|
) | rpl::on_next([=](const QSize &size) {
|
||||||
|
|||||||
@@ -9,8 +9,40 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
|
|
||||||
#include "editor/scene/scene.h"
|
#include "editor/scene/scene.h"
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
|
#include "ui/userpic_view.h"
|
||||||
|
|
||||||
namespace Editor {
|
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) {
|
QImage ImageModified(QImage image, const PhotoModifications &mods) {
|
||||||
Expects(!image.isNull());
|
Expects(!image.isNull());
|
||||||
@@ -32,6 +64,7 @@ QImage ImageModified(QImage image, const PhotoModifications &mods) {
|
|||||||
auto cropped = mods.crop.isValid()
|
auto cropped = mods.crop.isValid()
|
||||||
? image.copy(mods.crop)
|
? image.copy(mods.crop)
|
||||||
: image;
|
: image;
|
||||||
|
ApplyShapeMask(cropped, mods.cropType);
|
||||||
QTransform transform;
|
QTransform transform;
|
||||||
if (mods.flipped) {
|
if (mods.flipped) {
|
||||||
transform.scale(-1, 1);
|
transform.scale(-1, 1);
|
||||||
@@ -43,7 +76,11 @@ QImage ImageModified(QImage image, const PhotoModifications &mods) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PhotoModifications::empty() const {
|
bool PhotoModifications::empty() const {
|
||||||
return !angle && !flipped && !crop.isValid() && !paint;
|
return !angle
|
||||||
|
&& !flipped
|
||||||
|
&& !crop.isValid()
|
||||||
|
&& cropType == EditorData::CropType::Rect
|
||||||
|
&& !paint;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhotoModifications::operator bool() const {
|
PhotoModifications::operator bool() const {
|
||||||
|
|||||||
@@ -11,18 +11,6 @@ namespace Editor {
|
|||||||
|
|
||||||
class Scene;
|
class Scene;
|
||||||
|
|
||||||
struct PhotoModifications {
|
|
||||||
int angle = 0;
|
|
||||||
bool flipped = false;
|
|
||||||
QRect crop;
|
|
||||||
std::shared_ptr<Scene> paint = nullptr;
|
|
||||||
|
|
||||||
[[nodiscard]] bool empty() const;
|
|
||||||
[[nodiscard]] explicit operator bool() const;
|
|
||||||
~PhotoModifications();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EditorData {
|
struct EditorData {
|
||||||
enum class CropType {
|
enum class CropType {
|
||||||
Rect,
|
Rect,
|
||||||
@@ -35,6 +23,20 @@ struct EditorData {
|
|||||||
QSize exactSize;
|
QSize exactSize;
|
||||||
CropType cropType = CropType::Rect;
|
CropType cropType = CropType::Rect;
|
||||||
bool keepAspectRatio = false;
|
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<Scene> paint = nullptr;
|
||||||
|
|
||||||
|
[[nodiscard]] bool empty() const;
|
||||||
|
[[nodiscard]] explicit operator bool() const;
|
||||||
|
~PhotoModifications();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] QImage ImageModified(
|
[[nodiscard]] QImage ImageModified(
|
||||||
|
|||||||
Reference in New Issue
Block a user