File indexing completed on 2025-01-05 03:53:12

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2002-12-09
0007  * Description : a tool to print images
0008  *
0009  * SPDX-FileCopyrightText: 2002-2003 by Todd Shoemaker <todd at theshoemakers dot net>
0010  * SPDX-FileCopyrightText: 2007-2012 by Angelo Naselli <anaselli at linux dot it>
0011  * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #include "advprintphoto.h"
0018 
0019 // Qt includes
0020 
0021 #include <QFileInfo>
0022 #include <QPolygon>
0023 
0024 // KDE includes
0025 
0026 #include <klocalizedstring.h>
0027 
0028 // Local includes
0029 
0030 #include "digikam_debug.h"
0031 #include "previewloadthread.h"
0032 #include "advprintwizard.h"
0033 
0034 namespace DigikamGenericPrintCreatorPlugin
0035 {
0036 
0037 AdvPrintPhotoSize::AdvPrintPhotoSize()
0038     : m_label     (i18n("Unsupported Paper Size")),
0039       m_dpi       (0),
0040       m_autoRotate(false)
0041 {
0042 }
0043 
0044 AdvPrintPhotoSize::AdvPrintPhotoSize(const AdvPrintPhotoSize& other)
0045     : m_label     (other.m_label),
0046       m_dpi       (other.m_dpi),
0047       m_autoRotate(other.m_autoRotate),
0048       m_layouts   (other.m_layouts),
0049       m_icon      (other.m_icon)
0050 
0051 {
0052 }
0053 
0054 AdvPrintPhotoSize::~AdvPrintPhotoSize()
0055 {
0056 }
0057 
0058 // -----------------------------
0059 
0060 AdvPrintAdditionalInfo::AdvPrintAdditionalInfo()
0061     : m_unit                (0),
0062       m_printPosition       (0),
0063       m_scaleMode           (0),
0064       m_keepRatio           (true),
0065       m_autoRotate          (true),
0066       m_printWidth          (0.0),
0067       m_printHeight         (0.0),
0068       m_enlargeSmallerImages(false)
0069 {
0070 }
0071 
0072 AdvPrintAdditionalInfo::AdvPrintAdditionalInfo(const AdvPrintAdditionalInfo& other)
0073     : m_unit                (other.m_unit),
0074       m_printPosition       (other.m_printPosition),
0075       m_scaleMode           (other.m_scaleMode),
0076       m_keepRatio           (other.m_keepRatio),
0077       m_autoRotate          (other.m_autoRotate),
0078       m_printWidth          (other.m_printWidth),
0079       m_printHeight         (other.m_printHeight),
0080       m_enlargeSmallerImages(other.m_enlargeSmallerImages)
0081 {
0082 }
0083 
0084 AdvPrintAdditionalInfo::~AdvPrintAdditionalInfo()
0085 {
0086 }
0087 
0088 // -----------------------------
0089 
0090 AdvPrintCaptionInfo::AdvPrintCaptionInfo()
0091     : m_captionType (AdvPrintSettings::NONE),
0092       m_captionFont (QLatin1String("Sans Serif")),
0093       m_captionColor(Qt::yellow),
0094       m_captionSize (2),
0095       m_captionText (QLatin1String(""))
0096 {
0097 }
0098 
0099 AdvPrintCaptionInfo::AdvPrintCaptionInfo(const AdvPrintCaptionInfo& other)
0100     : m_captionType (other.m_captionType),
0101       m_captionFont (other.m_captionFont),
0102       m_captionColor(other.m_captionColor),
0103       m_captionSize (other.m_captionSize),
0104       m_captionText (other.m_captionText)
0105 {
0106 }
0107 
0108 AdvPrintCaptionInfo::~AdvPrintCaptionInfo()
0109 {
0110 }
0111 
0112 // -----------------------------
0113 
0114 AdvPrintPhoto::AdvPrintPhoto(int thumbnailSize, DInfoInterface* const iface)
0115     : m_url                 (QUrl()),
0116       m_thumbnailSize       (thumbnailSize),
0117       m_cropRegion          (QRect(-1, -1, -1, -1)),
0118       m_first               (false),
0119       m_copies              (1),
0120       m_rotation            (0),
0121       m_pAddInfo            (nullptr),
0122       m_pAdvPrintCaptionInfo(nullptr),
0123       m_iface               (iface),
0124       m_thumbnail           (nullptr),
0125       m_size                (nullptr)
0126 {
0127 }
0128 
0129 AdvPrintPhoto::AdvPrintPhoto(const AdvPrintPhoto& other)
0130     : m_url                 (other.m_url),
0131       m_thumbnailSize       (other.m_thumbnailSize),
0132       m_cropRegion          (other.m_cropRegion),
0133       m_first               (other.m_first),
0134       m_copies              (other.m_copies),
0135       m_rotation            (other.m_rotation),
0136       m_pAddInfo            (nullptr),
0137       m_pAdvPrintCaptionInfo(nullptr),
0138       m_iface               (other.m_iface),
0139       m_thumbnail           (nullptr),
0140       m_size                (nullptr)
0141 {
0142     if (other.m_pAddInfo)
0143     {
0144         m_pAddInfo = new AdvPrintAdditionalInfo(*other.m_pAddInfo);
0145     }
0146 
0147     if (other.m_pAdvPrintCaptionInfo)
0148     {
0149         m_pAdvPrintCaptionInfo = new AdvPrintCaptionInfo(*other.m_pAdvPrintCaptionInfo);
0150     }
0151 }
0152 
0153 AdvPrintPhoto::~AdvPrintPhoto()
0154 {
0155     delete m_thumbnail;
0156     delete m_size;
0157     delete m_pAddInfo;
0158     delete m_pAdvPrintCaptionInfo;
0159 }
0160 
0161 void AdvPrintPhoto::loadInCache()
0162 {
0163     // Load the thumbnail and size only once.
0164 
0165     delete m_thumbnail;
0166     DImg photo  = loadPhoto();
0167     m_thumbnail = new DImg(photo.smoothScale(m_thumbnailSize, m_thumbnailSize, Qt::KeepAspectRatio));
0168 
0169     delete m_size;
0170     m_size      = new QSize(photo.width(), photo.height());
0171 }
0172 
0173 DImg& AdvPrintPhoto::thumbnail()
0174 {
0175     if (!m_thumbnail)
0176     {
0177         loadInCache();
0178     }
0179 
0180     return *m_thumbnail;
0181 }
0182 
0183 DImg AdvPrintPhoto::loadPhoto()
0184 {
0185     return PreviewLoadThread::loadHighQualitySynchronously(m_url.toLocalFile());
0186 }
0187 
0188 QSize& AdvPrintPhoto::size()
0189 {
0190     if (m_size == nullptr)
0191     {
0192         loadInCache();
0193     }
0194 
0195     return *m_size;
0196 }
0197 
0198 int AdvPrintPhoto::width()
0199 {
0200     return size().width();
0201 }
0202 
0203 int AdvPrintPhoto::height()
0204 {
0205     return size().height();
0206 }
0207 
0208 double AdvPrintPhoto::scaleWidth(double unitToInches)
0209 {
0210     Q_ASSERT(m_pAddInfo != nullptr);
0211 
0212     m_cropRegion = QRect(0, 0,
0213                          (int)(m_pAddInfo->m_printWidth  * unitToInches),
0214                          (int)(m_pAddInfo->m_printHeight * unitToInches));
0215 
0216     return (m_pAddInfo->m_printWidth * unitToInches);
0217 }
0218 
0219 double AdvPrintPhoto::scaleHeight(double unitToInches)
0220 {
0221     Q_ASSERT(m_pAddInfo != nullptr);
0222 
0223     m_cropRegion = QRect(0, 0,
0224                          (int)(m_pAddInfo->m_printWidth  * unitToInches),
0225                          (int)(m_pAddInfo->m_printHeight * unitToInches));
0226 
0227     return (m_pAddInfo->m_printHeight * unitToInches);
0228 }
0229 
0230 QTransform AdvPrintPhoto::updateCropRegion(int woutlay, int houtlay, bool autoRotate)
0231 {
0232     QSize thmSize        = thumbnail().size();
0233     QRect imgRect        = QRect(0, 0, size().width(), size().height());
0234     bool resetCropRegion = (m_cropRegion == QRect(-1, -1, -1, -1));
0235 
0236     if (resetCropRegion)
0237     {
0238         // First, let's see if we should rotate
0239 
0240         if (autoRotate)
0241         {
0242             if ((m_rotation == 0) &&
0243                 (((woutlay > houtlay) && (thmSize.height() > thmSize.width())) ||
0244                  ((houtlay > woutlay) && (thmSize.width()  > thmSize.height()))))
0245             {
0246                 // We will perform a rotation
0247 
0248                 m_rotation = 90;
0249             }
0250         }
0251     }
0252     else
0253     {
0254         // Does the crop region need updating (but the image shouldn't be rotated)?
0255 
0256         resetCropRegion = (m_cropRegion == QRect(-2, -2, -2, -2));
0257     }
0258 
0259     // Rotate the image rectangle.
0260 
0261     QTransform matrix;
0262     matrix.rotate(m_rotation);
0263     imgRect = matrix.mapToPolygon(imgRect).boundingRect();
0264     imgRect.translate((-1)*imgRect.x(), (-1)*imgRect.y());
0265 
0266     // Size the rectangle based on the minimum image dimension.
0267 
0268     int w   = imgRect.width();
0269     int h   = imgRect.height();
0270 
0271     if (w < h)
0272     {
0273         h = AdvPrintWizard::normalizedInt((double)w * ((double)houtlay / (double)woutlay));
0274 
0275         if (h > imgRect.height())
0276         {
0277             h = imgRect.height();
0278             w = AdvPrintWizard::normalizedInt((double)h * ((double)woutlay / (double)houtlay));
0279         }
0280     }
0281     else
0282     {
0283         w = AdvPrintWizard::normalizedInt((double)h * ((double)woutlay / (double)houtlay));
0284 
0285         if (w > imgRect.width())
0286         {
0287             w = imgRect.width();
0288             h = AdvPrintWizard::normalizedInt((double)w * ((double)houtlay / (double)woutlay));
0289         }
0290     }
0291 
0292     if (resetCropRegion)
0293     {
0294         m_cropRegion = QRect((imgRect.width()  / 2) - (w / 2),
0295                              (imgRect.height() / 2) - (h / 2),
0296                              w, h);
0297     }
0298 
0299     return matrix;
0300 }
0301 
0302 } // Namespace Digikam