1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2002-12-09
7 * Description : a tool to print images
8 *
9 * Copyright (C) 2002-2003 by Todd Shoemaker <todd at theshoemakers dot net>
10 * Copyright (C) 2007-2012 by Angelo Naselli <anaselli at linux dot it>
11 * Copyright (C) 2006-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
12 *
13 * This program is free software; you can redistribute it
14 * and/or modify it under the terms of the GNU General
15 * Public License as published by the Free Software Foundation;
16 * either version 2, or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * ============================================================ */
24
25 #include "advprintphoto.h"
26
27 // Qt includes
28
29 #include <QFileInfo>
30 #include <QPolygon>
31
32 // KDE includes
33
34 #include <klocalizedstring.h>
35
36 // Local includes
37
38 #include "digikam_debug.h"
39 #include "previewloadthread.h"
40 #include "advprintwizard.h"
41
42 namespace DigikamGenericPrintCreatorPlugin
43 {
44
AdvPrintPhotoSize()45 AdvPrintPhotoSize::AdvPrintPhotoSize()
46 : m_label (i18n("Unsupported Paper Size")),
47 m_dpi (0),
48 m_autoRotate(false)
49 {
50 }
51
AdvPrintPhotoSize(const AdvPrintPhotoSize & other)52 AdvPrintPhotoSize::AdvPrintPhotoSize(const AdvPrintPhotoSize& other)
53 : m_label (other.m_label),
54 m_dpi (other.m_dpi),
55 m_autoRotate(other.m_autoRotate),
56 m_layouts (other.m_layouts),
57 m_icon (other.m_icon)
58
59 {
60 }
61
~AdvPrintPhotoSize()62 AdvPrintPhotoSize::~AdvPrintPhotoSize()
63 {
64 }
65
66 // -----------------------------
67
AdvPrintAdditionalInfo()68 AdvPrintAdditionalInfo::AdvPrintAdditionalInfo()
69 : m_unit (0),
70 m_printPosition (0),
71 m_scaleMode (0),
72 m_keepRatio (true),
73 m_autoRotate (true),
74 m_printWidth (0.0),
75 m_printHeight (0.0),
76 m_enlargeSmallerImages(false)
77 {
78 }
79
AdvPrintAdditionalInfo(const AdvPrintAdditionalInfo & other)80 AdvPrintAdditionalInfo::AdvPrintAdditionalInfo(const AdvPrintAdditionalInfo& other)
81 : m_unit (other.m_unit),
82 m_printPosition (other.m_printPosition),
83 m_scaleMode (other.m_scaleMode),
84 m_keepRatio (other.m_keepRatio),
85 m_autoRotate (other.m_autoRotate),
86 m_printWidth (other.m_printWidth),
87 m_printHeight (other.m_printHeight),
88 m_enlargeSmallerImages(other.m_enlargeSmallerImages)
89 {
90 }
91
~AdvPrintAdditionalInfo()92 AdvPrintAdditionalInfo::~AdvPrintAdditionalInfo()
93 {
94 }
95
96 // -----------------------------
97
AdvPrintCaptionInfo()98 AdvPrintCaptionInfo::AdvPrintCaptionInfo()
99 : m_captionType (AdvPrintSettings::NONE),
100 m_captionFont (QLatin1String("Sans Serif")),
101 m_captionColor(Qt::yellow),
102 m_captionSize (2),
103 m_captionText (QLatin1String(""))
104 {
105 }
106
AdvPrintCaptionInfo(const AdvPrintCaptionInfo & other)107 AdvPrintCaptionInfo::AdvPrintCaptionInfo(const AdvPrintCaptionInfo& other)
108 : m_captionType (other.m_captionType),
109 m_captionFont (other.m_captionFont),
110 m_captionColor(other.m_captionColor),
111 m_captionSize (other.m_captionSize),
112 m_captionText (other.m_captionText)
113 {
114 }
115
~AdvPrintCaptionInfo()116 AdvPrintCaptionInfo::~AdvPrintCaptionInfo()
117 {
118 }
119
120 // -----------------------------
121
AdvPrintPhoto(int thumbnailSize,DInfoInterface * const iface)122 AdvPrintPhoto::AdvPrintPhoto(int thumbnailSize, DInfoInterface* const iface)
123 : m_url (QUrl()),
124 m_thumbnailSize (thumbnailSize),
125 m_cropRegion (QRect(-1, -1, -1, -1)),
126 m_first (false),
127 m_copies (1),
128 m_rotation (0),
129 m_pAddInfo (nullptr),
130 m_pAdvPrintCaptionInfo(nullptr),
131 m_iface (iface),
132 m_thumbnail (nullptr),
133 m_size (nullptr)
134 {
135 }
136
AdvPrintPhoto(const AdvPrintPhoto & other)137 AdvPrintPhoto::AdvPrintPhoto(const AdvPrintPhoto& other)
138 : m_url (other.m_url),
139 m_thumbnailSize (other.m_thumbnailSize),
140 m_cropRegion (other.m_cropRegion),
141 m_first (other.m_first),
142 m_copies (other.m_copies),
143 m_rotation (other.m_rotation),
144 m_pAddInfo (nullptr),
145 m_pAdvPrintCaptionInfo(nullptr),
146 m_iface (other.m_iface),
147 m_thumbnail (nullptr),
148 m_size (nullptr)
149 {
150 if (other.m_pAddInfo)
151 {
152 m_pAddInfo = new AdvPrintAdditionalInfo(*other.m_pAddInfo);
153 }
154
155 if (other.m_pAdvPrintCaptionInfo)
156 {
157 m_pAdvPrintCaptionInfo = new AdvPrintCaptionInfo(*other.m_pAdvPrintCaptionInfo);
158 }
159 }
160
~AdvPrintPhoto()161 AdvPrintPhoto::~AdvPrintPhoto()
162 {
163 delete m_thumbnail;
164 delete m_size;
165 delete m_pAddInfo;
166 delete m_pAdvPrintCaptionInfo;
167 }
168
loadInCache()169 void AdvPrintPhoto::loadInCache()
170 {
171 // Load the thumbnail and size only once.
172
173 delete m_thumbnail;
174 DImg photo = loadPhoto();
175 m_thumbnail = new DImg(photo.smoothScale(m_thumbnailSize, m_thumbnailSize, Qt::KeepAspectRatio));
176
177 delete m_size;
178 m_size = new QSize(photo.width(), photo.height());
179 }
180
thumbnail()181 DImg& AdvPrintPhoto::thumbnail()
182 {
183 if (!m_thumbnail)
184 {
185 loadInCache();
186 }
187
188 return *m_thumbnail;
189 }
190
loadPhoto()191 DImg AdvPrintPhoto::loadPhoto()
192 {
193 return PreviewLoadThread::loadHighQualitySynchronously(m_url.toLocalFile());
194 }
195
size()196 QSize& AdvPrintPhoto::size()
197 {
198 if (m_size == nullptr)
199 {
200 loadInCache();
201 }
202
203 return *m_size;
204 }
205
width()206 int AdvPrintPhoto::width()
207 {
208 return size().width();
209 }
210
height()211 int AdvPrintPhoto::height()
212 {
213 return size().height();
214 }
215
scaleWidth(double unitToInches)216 double AdvPrintPhoto::scaleWidth(double unitToInches)
217 {
218 Q_ASSERT(m_pAddInfo != nullptr);
219
220 m_cropRegion = QRect(0, 0,
221 (int)(m_pAddInfo->m_printWidth * unitToInches),
222 (int)(m_pAddInfo->m_printHeight * unitToInches));
223
224 return (m_pAddInfo->m_printWidth * unitToInches);
225 }
226
scaleHeight(double unitToInches)227 double AdvPrintPhoto::scaleHeight(double unitToInches)
228 {
229 Q_ASSERT(m_pAddInfo != nullptr);
230
231 m_cropRegion = QRect(0, 0,
232 (int)(m_pAddInfo->m_printWidth * unitToInches),
233 (int)(m_pAddInfo->m_printHeight * unitToInches));
234
235 return (m_pAddInfo->m_printHeight * unitToInches);
236 }
237
updateCropRegion(int woutlay,int houtlay,bool autoRotate)238 QMatrix AdvPrintPhoto::updateCropRegion(int woutlay, int houtlay, bool autoRotate)
239 {
240 QSize thmSize = thumbnail().size();
241 QRect imgRect = QRect(0, 0, size().width(), size().height());
242 bool resetCropRegion = (m_cropRegion == QRect(-1, -1, -1, -1));
243
244 if (resetCropRegion)
245 {
246 // First, let's see if we should rotate
247
248 if (autoRotate)
249 {
250 if ((m_rotation == 0) &&
251 (((woutlay > houtlay) && (thmSize.height() > thmSize.width())) ||
252 ((houtlay > woutlay) && (thmSize.width() > thmSize.height()))))
253 {
254 // We will perform a rotation
255
256 m_rotation = 90;
257 }
258 }
259 }
260 else
261 {
262 // Does the crop region need updating (but the image shouldn't be rotated)?
263
264 resetCropRegion = (m_cropRegion == QRect(-2, -2, -2, -2));
265 }
266
267 // Rotate the image rectangle.
268
269 QMatrix matrix;
270 matrix.rotate(m_rotation);
271 imgRect = matrix.mapToPolygon(imgRect).boundingRect();
272 imgRect.translate((-1)*imgRect.x(), (-1)*imgRect.y());
273
274 // Size the rectangle based on the minimum image dimension.
275
276 int w = imgRect.width();
277 int h = imgRect.height();
278
279 if (w < h)
280 {
281 h = AdvPrintWizard::normalizedInt((double)w * ((double)houtlay / (double)woutlay));
282
283 if (h > imgRect.height())
284 {
285 h = imgRect.height();
286 w = AdvPrintWizard::normalizedInt((double)h * ((double)woutlay / (double)houtlay));
287 }
288 }
289 else
290 {
291 w = AdvPrintWizard::normalizedInt((double)h * ((double)woutlay / (double)houtlay));
292
293 if (w > imgRect.width())
294 {
295 w = imgRect.width();
296 h = AdvPrintWizard::normalizedInt((double)w * ((double)houtlay / (double)woutlay));
297 }
298 }
299
300 if (resetCropRegion)
301 {
302 m_cropRegion = QRect((imgRect.width() / 2) - (w / 2),
303 (imgRect.height() / 2) - (h / 2),
304 w, h);
305 }
306
307 return matrix;
308 }
309
310 } // Namespace Digikam
311