File indexing completed on 2024-05-05 04:05:48

0001 /*
0002     SPDX-FileCopyrightText: 2009 Stefan Majewsky <majewsky@gmx.net>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "slicerjob.h"
0008 #include "slicer.h"
0009 
0010 #include <QPainter>
0011 
0012 //BEGIN Pala::SlicerJobPrivate
0013 
0014 class Pala::SlicerJobPrivate
0015 {
0016     public:
0017         SlicerJobPrivate() : m_mode(nullptr) {}
0018 
0019         QMap<QByteArray, QVariant> m_args;
0020         QImage m_image;
0021         const Pala::SlicerMode* m_mode;
0022 
0023         QMap<int, QImage> m_pieces;
0024         QMap<int, QPoint> m_pieceOffsets;
0025         QList<QPair<int, int> > m_relations;
0026 };
0027 
0028 //END Pala::SlicerJobPrivate
0029 
0030 Pala::SlicerJob::SlicerJob(const QImage& image, const QMap<QByteArray, QVariant>& args)
0031     : d_ptr(new SlicerJobPrivate)
0032 {
0033     Q_D(SlicerJob);
0034     d->m_args = args;
0035     d->m_image = image;
0036 }
0037 
0038 Pala::SlicerJob::~SlicerJob() = default;
0039 
0040 QVariant Pala::SlicerJob::argument(const QByteArray& key) const
0041 {
0042     Q_D(const SlicerJob);
0043     return d->m_args.value(key, QVariant());
0044 }
0045 
0046 QImage Pala::SlicerJob::image() const
0047 {
0048     Q_D(const SlicerJob);
0049     return d->m_image;
0050 }
0051 
0052 const Pala::SlicerMode* Pala::SlicerJob::mode() const
0053 {
0054     Q_D(const SlicerJob);
0055     return d->m_mode;
0056 }
0057 
0058 QMap<int, QImage> Pala::SlicerJob::pieces() const
0059 {
0060     Q_D(const SlicerJob);
0061     return d->m_pieces;
0062 }
0063 
0064 QMap<int, QPoint> Pala::SlicerJob::pieceOffsets() const
0065 {
0066     Q_D(const SlicerJob);
0067     return d->m_pieceOffsets;
0068 }
0069 
0070 QList<QPair<int, int> > Pala::SlicerJob::relations() const
0071 {
0072     Q_D(const SlicerJob);
0073     return d->m_relations;
0074 }
0075 
0076 void Pala::SlicerJob::setMode(const Pala::SlicerMode* mode)
0077 {
0078     Q_D(SlicerJob);
0079     d->m_mode = mode;
0080 }
0081 
0082 void Pala::SlicerJob::respectSlicerFlags(int flags)
0083 {
0084     Q_D(SlicerJob);
0085     if (!(flags & Pala::Slicer::AllowFullTransparency))
0086     {
0087         QImage image(d->m_image.size(), d->m_image.format());
0088         QColor blackShade(Qt::black); blackShade.setAlpha(42);
0089         image.fill(blackShade.rgba());
0090         QPainter painter(&image);
0091         painter.drawImage(QPoint(), d->m_image);
0092         painter.end();
0093         d->m_image = image;
0094     }
0095 }
0096 
0097 void Pala::SlicerJob::addPiece(int pieceID, const QImage& image, const QPoint& offset)
0098 {
0099     Q_D(SlicerJob);
0100     d->m_pieces.insert(pieceID, image);
0101     d->m_pieceOffsets.insert(pieceID, offset);
0102 }
0103 
0104 //A modified version of QImage::copy, which avoids rendering errors even if rect is outside the bounds of the source image.
0105 static
0106 QImage safeQImageCopy(const QImage& source, const QRect& rect)
0107 {
0108     QRect targetRect(QPoint(), rect.size());
0109     //copy image
0110     QImage target(rect.size(), source.format());
0111     QPainter p(&target);
0112     p.drawImage(targetRect, source, rect);
0113     p.end();
0114     return target;
0115     //Strangely, source.copy(rect) does not work. It produces black borders.
0116 }
0117 
0118 void Pala::SlicerJob::addPieceFromMask(int pieceID, const QImage& mask, const QPoint& offset)
0119 {
0120     Q_D(SlicerJob);
0121     QImage pieceImage(mask);
0122     QPainter painter(&pieceImage);
0123     painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
0124     painter.drawImage(QPoint(), safeQImageCopy(d->m_image, QRect(offset, mask.size())));
0125     painter.end();
0126     addPiece(pieceID, pieceImage, offset);
0127 }
0128 
0129 void Pala::SlicerJob::addRelation(int pieceID1, int pieceID2)
0130 {
0131     Q_D(SlicerJob);
0132     d->m_relations << QPair<int, int>(pieceID1, pieceID2);
0133 }