File: | sharp/sharpenfilter.cpp |
Warning: | line 218, column 19 Assigned value is garbage or undefined |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* ============================================================ | |||
2 | * | |||
3 | * This file is a part of digiKam project | |||
4 | * https://www.digikam.org | |||
5 | * | |||
6 | * Date : 2005-17-07 | |||
7 | * Description : A Sharpen threaded image filter. | |||
8 | * | |||
9 | * SPDX-FileCopyrightText: 2005-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> | |||
10 | * SPDX-FileCopyrightText: 2010 by Martin Klapetek <martin dot klapetek at gmail dot com> | |||
11 | * SPDX-FileCopyrightText: 2002 by Daniel M. Duley <mosfet at kde dot org> | |||
12 | * | |||
13 | * SPDX-License-Identifier: GPL-2.0-or-later | |||
14 | * | |||
15 | * ============================================================ */ | |||
16 | ||||
17 | #define SQ2PI2.50662827463100024161235523934010416269302368164062 2.50662827463100024161235523934010416269302368164062 | |||
18 | #define Epsilon1.0e-12 1.0e-12 | |||
19 | ||||
20 | #include "sharpenfilter.h" | |||
21 | ||||
22 | // C++ includes | |||
23 | ||||
24 | #include <cmath> | |||
25 | #include <cstdlib> | |||
26 | ||||
27 | // Qt includes | |||
28 | ||||
29 | #include <QtConcurrent> // krazy:exclude=includes | |||
30 | ||||
31 | // Local includes | |||
32 | ||||
33 | #include "digikam_debug.h" | |||
34 | #include "digikam_globals_p.h" // For KF6::Ki18n deprecated | |||
35 | ||||
36 | namespace Digikam | |||
37 | { | |||
38 | ||||
39 | SharpenFilter::SharpenFilter(QObject* const parent) | |||
40 | : DImgThreadedFilter(parent) | |||
41 | { | |||
42 | initFilter(); | |||
43 | } | |||
44 | ||||
45 | SharpenFilter::SharpenFilter(DImg* const orgImage, QObject* const parent, double radius, double sigma) | |||
46 | : DImgThreadedFilter(orgImage, parent, QLatin1String("Sharpen")) | |||
47 | { | |||
48 | m_radius = radius; | |||
49 | m_sigma = sigma; | |||
50 | initFilter(); | |||
51 | } | |||
52 | ||||
53 | SharpenFilter::SharpenFilter(DImgThreadedFilter* const parentFilter, | |||
54 | const DImg& orgImage, const DImg& destImage, | |||
55 | int progressBegin, int progressEnd, double radius, double sigma) | |||
56 | : DImgThreadedFilter(parentFilter, orgImage, destImage, progressBegin, progressEnd, | |||
57 | parentFilter->filterName() + QLatin1String(": Sharpen")) | |||
58 | { | |||
59 | m_radius = radius; | |||
60 | m_sigma = sigma; | |||
61 | ||||
62 | // We need to provide support for orgImage == destImage. | |||
63 | // The algorithm does not support this out of the box, so use a temporary. | |||
64 | ||||
65 | if (orgImage.bits() == destImage.bits()) | |||
| ||||
66 | { | |||
67 | m_destImage = DImg(destImage.width(), destImage.height(), destImage.sixteenBit()); | |||
68 | } | |||
69 | ||||
70 | this->filterImage(); | |||
71 | ||||
72 | if (orgImage.bits() == destImage.bits()) | |||
73 | { | |||
74 | memcpy(destImage.bits(), m_destImage.bits(), m_destImage.numBytes()); | |||
75 | } | |||
76 | } | |||
77 | ||||
78 | SharpenFilter::~SharpenFilter() | |||
79 | { | |||
80 | cancelFilter(); | |||
81 | } | |||
82 | ||||
83 | QString SharpenFilter::DisplayableName() | |||
84 | { | |||
85 | return QString::fromUtf8(I18N_NOOP("Sharpen")kli18n("Sharpen").untranslatedText()); | |||
86 | } | |||
87 | ||||
88 | void SharpenFilter::filterImage() | |||
89 | { | |||
90 | sharpenImage(m_radius, m_sigma); | |||
91 | } | |||
92 | ||||
93 | /** | |||
94 | * Function to apply the sharpen filter on an image | |||
95 | */ | |||
96 | void SharpenFilter::sharpenImage(double radius, double sigma) | |||
97 | { | |||
98 | if (m_orgImage.isNull()) | |||
99 | { | |||
100 | qCWarning(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/mnt/data/Devel/8.x/core/libs/dimg/filters/sharp/sharpenfilter.cpp" ), 100, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "No image data available!"; | |||
101 | ||||
102 | return; | |||
103 | } | |||
104 | ||||
105 | if (radius <= 0.0) | |||
106 | { | |||
107 | m_destImage = m_orgImage; | |||
108 | ||||
109 | return; | |||
110 | } | |||
111 | ||||
112 | double alpha, normalize = 0.0; | |||
113 | long i = 0, u, v; | |||
114 | ||||
115 | int kernelWidth = getOptimalKernelWidth(radius, sigma); | |||
116 | int halfKernelWidth = kernelWidth / 2; | |||
117 | ||||
118 | if ((int)m_orgImage.width() < kernelWidth) | |||
119 | { | |||
120 | qCWarning(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/mnt/data/Devel/8.x/core/libs/dimg/filters/sharp/sharpenfilter.cpp" ), 120, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "Image is smaller than radius!"; | |||
121 | ||||
122 | return; | |||
123 | } | |||
124 | ||||
125 | QScopedArrayPointer<double> kernel(new double[kernelWidth * kernelWidth]{}); | |||
126 | ||||
127 | if (kernel.isNull()) | |||
128 | { | |||
129 | qCWarning(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/mnt/data/Devel/8.x/core/libs/dimg/filters/sharp/sharpenfilter.cpp" ), 129, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "Unable to allocate memory!"; | |||
130 | ||||
131 | return; | |||
132 | } | |||
133 | ||||
134 | for (v = -halfKernelWidth ; v <= halfKernelWidth ; ++v) | |||
135 | { | |||
136 | for (u = -halfKernelWidth ; u <= halfKernelWidth ; ++u) | |||
137 | { | |||
138 | alpha = exp(-((double) u * u + v * v) / (2.0 * sigma * sigma)); | |||
139 | kernel[i] = alpha / (2.0 * M_PI3.14159265358979323846 * sigma * sigma); | |||
140 | normalize += kernel[i]; | |||
141 | ++i; | |||
142 | } | |||
143 | } | |||
144 | ||||
145 | kernel[i / 2] = (-2.0) * normalize; | |||
146 | convolveImage(kernelWidth, kernel.data()); | |||
147 | } | |||
148 | ||||
149 | void SharpenFilter::convolveImageMultithreaded(const Args& prm) | |||
150 | { | |||
151 | double maxClamp = m_destImage.sixteenBit() ? 16777215.0 : 65535.0; | |||
152 | double* k = nullptr; | |||
153 | double red, green, blue, alpha; | |||
154 | int mx, my, sx, sy, mcx, mcy; | |||
155 | DColor color; | |||
156 | ||||
157 | for (uint x = prm.start ; runningFlag() && (x < prm.stop) ; ++x) | |||
158 | { | |||
159 | k = prm.normal_kernel; | |||
160 | red = green = blue = alpha = 0; | |||
161 | sy = prm.y - prm.halfKernelWidth; | |||
162 | ||||
163 | for (mcy = 0 ; runningFlag() && (mcy < prm.kernelWidth) ; ++mcy, ++sy) | |||
164 | { | |||
165 | my = (sy < 0) ? 0 : (sy > (int)m_destImage.height() - 1) ? m_destImage.height() - 1 : sy; | |||
166 | sx = x + (-prm.halfKernelWidth); | |||
167 | ||||
168 | for (mcx = 0 ; runningFlag() && (mcx < prm.kernelWidth) ; ++mcx, ++sx) | |||
169 | { | |||
170 | mx = (sx < 0) ? 0 : (sx > (int)m_destImage.width() - 1) ? m_destImage.width() - 1 : sx; | |||
171 | color = m_orgImage.getPixelColor(mx, my); | |||
172 | red += (*k) * (color.red() * 257.0); | |||
173 | green += (*k) * (color.green() * 257.0); | |||
174 | blue += (*k) * (color.blue() * 257.0); | |||
175 | alpha += (*k) * (color.alpha() * 257.0); | |||
176 | ++k; | |||
177 | } | |||
178 | } | |||
179 | ||||
180 | red = red < 0.0 ? 0.0 : (red > maxClamp) ? maxClamp : red + 0.5; | |||
181 | green = green < 0.0 ? 0.0 : (green > maxClamp) ? maxClamp : green + 0.5; | |||
182 | blue = blue < 0.0 ? 0.0 : (blue > maxClamp) ? maxClamp : blue + 0.5; | |||
183 | alpha = alpha < 0.0 ? 0.0 : (alpha > maxClamp) ? maxClamp : alpha + 0.5; | |||
184 | ||||
185 | m_destImage.setPixelColor(x, prm.y, DColor((int)(red / 257UL), (int)(green / 257UL), | |||
186 | (int)(blue / 257UL), (int)(alpha / 257UL), | |||
187 | m_destImage.sixteenBit())); | |||
188 | } | |||
189 | } | |||
190 | ||||
191 | bool SharpenFilter::convolveImage(const unsigned int order, const double* const kernel) | |||
192 | { | |||
193 | int progress; | |||
194 | double normalize = 0.0; | |||
195 | ||||
196 | Args prm; | |||
197 | prm.kernelWidth = order; | |||
198 | prm.halfKernelWidth = prm.kernelWidth / 2; | |||
199 | ||||
200 | if ((prm.kernelWidth % 2) == 0) | |||
201 | { | |||
202 | qCWarning(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/mnt/data/Devel/8.x/core/libs/dimg/filters/sharp/sharpenfilter.cpp" ), 202, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "Kernel width must be an odd number!"; | |||
203 | ||||
204 | return false; | |||
205 | } | |||
206 | ||||
207 | QScopedArrayPointer<double> normal_kernel(new double[prm.kernelWidth * prm.kernelWidth]{}); | |||
208 | ||||
209 | if (normal_kernel.isNull()) | |||
210 | { | |||
211 | qCWarning(DIGIKAM_DIMG_LOG)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG)()); qt_category; qt_category.control = false ) QMessageLogger(static_cast<const char *>("/mnt/data/Devel/8.x/core/libs/dimg/filters/sharp/sharpenfilter.cpp" ), 211, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "Unable to allocate memory!"; | |||
212 | ||||
213 | return false; | |||
214 | } | |||
215 | ||||
216 | for (long i = 0 ; i < (prm.kernelWidth * prm.kernelWidth) ; ++i) | |||
217 | { | |||
218 | normalize += kernel[i]; | |||
| ||||
219 | } | |||
220 | ||||
221 | if (fabs(normalize) <= Epsilon1.0e-12) | |||
222 | { | |||
223 | normalize = 1.0; | |||
224 | } | |||
225 | ||||
226 | normalize = 1.0 / normalize; | |||
227 | ||||
228 | for (long i = 0 ; i < (prm.kernelWidth * prm.kernelWidth) ; ++i) | |||
229 | { | |||
230 | normal_kernel[i] = normalize * kernel[i]; | |||
231 | } | |||
232 | ||||
233 | prm.normal_kernel = normal_kernel.data(); | |||
234 | QList<int> vals = multithreadedSteps(m_destImage.width()); | |||
235 | ||||
236 | for (uint y = 0 ; runningFlag() && (y < m_destImage.height()) ; ++y) | |||
237 | { | |||
238 | QList <QFuture<void> > tasks; | |||
239 | ||||
240 | for (int j = 0 ; runningFlag() && (j < vals.count()-1) ; ++j) | |||
241 | { | |||
242 | prm.start = vals[j]; | |||
243 | prm.stop = vals[j+1]; | |||
244 | prm.y = y; | |||
245 | ||||
246 | tasks.append(QtConcurrent::run( | |||
247 | ||||
248 | #if (QT_VERSION((6<<16)|(8<<8)|(0)) >= QT_VERSION_CHECK(6, 0, 0)((6<<16)|(0<<8)|(0))) | |||
249 | ||||
250 | &SharpenFilter::convolveImageMultithreaded, this, | |||
251 | ||||
252 | #else | |||
253 | ||||
254 | this, &SharpenFilter::convolveImageMultithreaded, | |||
255 | ||||
256 | #endif | |||
257 | ||||
258 | prm | |||
259 | ) | |||
260 | ); | |||
261 | } | |||
262 | ||||
263 | for (QFuture<void> t : std::as_const(tasks)) | |||
264 | { | |||
265 | t.waitForFinished(); | |||
266 | } | |||
267 | ||||
268 | progress = (int)(((double)y * 100.0) / m_destImage.height()); | |||
269 | ||||
270 | if ((progress % 5) == 0) | |||
271 | { | |||
272 | postProgress(progress); | |||
273 | } | |||
274 | } | |||
275 | ||||
276 | return true; | |||
277 | } | |||
278 | ||||
279 | int SharpenFilter::getOptimalKernelWidth(double radius, double sigma) | |||
280 | { | |||
281 | double normalize, value; | |||
282 | long kernelWidth; | |||
283 | long u; | |||
284 | ||||
285 | if (radius > 0.0) | |||
286 | { | |||
287 | return((int)(2.0 * ceil(radius) + 1.0)); | |||
288 | } | |||
289 | ||||
290 | for (kernelWidth = 5 ; ; ) | |||
291 | { | |||
292 | normalize = 0.0; | |||
293 | ||||
294 | for (u = (-kernelWidth / 2) ; u <= (kernelWidth / 2) ; ++u) | |||
295 | { | |||
296 | normalize += exp(-((double) u * u) / (2.0 * sigma * sigma)) / (SQ2PI2.50662827463100024161235523934010416269302368164062 * sigma); | |||
297 | } | |||
298 | ||||
299 | u = kernelWidth / 2; | |||
300 | value = exp(-((double) u * u) / (2.0 * sigma * sigma)) / (SQ2PI2.50662827463100024161235523934010416269302368164062 * sigma) / normalize; | |||
301 | ||||
302 | if ((long)(65535 * value) <= 0) | |||
303 | { | |||
304 | break; | |||
305 | } | |||
306 | ||||
307 | kernelWidth += 2; | |||
308 | } | |||
309 | ||||
310 | return ((int)kernelWidth - 2); | |||
311 | } | |||
312 | ||||
313 | FilterAction SharpenFilter::filterAction() | |||
314 | { | |||
315 | FilterAction action(FilterIdentifier(), CurrentVersion()); | |||
316 | action.setDisplayableName(DisplayableName()); | |||
317 | ||||
318 | action.addParameter(QLatin1String("radius"), m_radius); | |||
319 | action.addParameter(QLatin1String("sigma"), m_sigma); | |||
320 | ||||
321 | return action; | |||
322 | } | |||
323 | ||||
324 | void SharpenFilter::readParameters(const Digikam::FilterAction& action) | |||
325 | { | |||
326 | m_radius = action.parameter(QLatin1String("radius")).toDouble(); | |||
327 | m_sigma = action.parameter(QLatin1String("sigma")).toDouble(); | |||
328 | } | |||
329 | ||||
330 | } // namespace Digikam | |||
331 | ||||
332 | #include "moc_sharpenfilter.cpp" |
1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QSCOPEDPOINTER_H |
5 | #define QSCOPEDPOINTER_H |
6 | |
7 | #include <QtCore/qglobal.h> |
8 | |
9 | #include <stdlib.h> |
10 | |
11 | QT_BEGIN_NAMESPACE |
12 | |
13 | template <typename T> |
14 | struct QScopedPointerDeleter |
15 | { |
16 | static inline void cleanup(T *pointer) noexcept |
17 | { |
18 | // Enforce a complete type. |
19 | // If you get a compile error here, read the section on forward declared |
20 | // classes in the QScopedPointer documentation. |
21 | typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; |
22 | (void) sizeof(IsIncompleteType); |
23 | |
24 | delete pointer; |
25 | } |
26 | void operator()(T *pointer) const noexcept |
27 | { |
28 | cleanup(pointer); |
29 | } |
30 | }; |
31 | |
32 | template <typename T> |
33 | struct QScopedPointerArrayDeleter |
34 | { |
35 | static inline void cleanup(T *pointer) noexcept |
36 | { |
37 | // Enforce a complete type. |
38 | // If you get a compile error here, read the section on forward declared |
39 | // classes in the QScopedPointer documentation. |
40 | typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; |
41 | (void) sizeof(IsIncompleteType); |
42 | |
43 | delete[] pointer; |
44 | } |
45 | void operator()(T *pointer) const noexcept |
46 | { |
47 | cleanup(pointer); |
48 | } |
49 | }; |
50 | |
51 | struct QScopedPointerPodDeleter |
52 | { |
53 | static inline void cleanup(void *pointer) noexcept { free(pointer); } |
54 | void operator()(void *pointer) const noexcept { cleanup(pointer); } |
55 | }; |
56 | |
57 | #ifndef QT_NO_QOBJECT |
58 | template <typename T> |
59 | struct QScopedPointerObjectDeleteLater |
60 | { |
61 | static inline void cleanup(T *pointer) { if (pointer) pointer->deleteLater(); } |
62 | void operator()(T *pointer) const { cleanup(pointer); } |
63 | }; |
64 | |
65 | class QObject; |
66 | typedef QScopedPointerObjectDeleteLater<QObject> QScopedPointerDeleteLater; |
67 | #endif |
68 | |
69 | template <typename T, typename Cleanup = QScopedPointerDeleter<T> > |
70 | class QScopedPointer |
71 | { |
72 | public: |
73 | Q_NODISCARD_CTOR[[nodiscard]] |
74 | explicit QScopedPointer(T *p = nullptr) noexcept : d(p) |
75 | { |
76 | } |
77 | |
78 | inline ~QScopedPointer() |
79 | { |
80 | T *oldD = this->d; |
81 | Cleanup::cleanup(oldD); |
82 | } |
83 | |
84 | inline T &operator*() const |
85 | { |
86 | Q_ASSERT(d)((d) ? static_cast<void>(0) : qt_assert("d", "/opt/qt6/include/QtCore/qscopedpointer.h" , 86)); |
87 | return *d; |
88 | } |
89 | |
90 | T *operator->() const noexcept |
91 | { |
92 | return d; |
93 | } |
94 | |
95 | bool operator!() const noexcept |
96 | { |
97 | return !d; |
98 | } |
99 | |
100 | explicit operator bool() const |
101 | { |
102 | return !isNull(); |
103 | } |
104 | |
105 | T *data() const noexcept |
106 | { |
107 | return d; |
108 | } |
109 | |
110 | T *get() const noexcept |
111 | { |
112 | return d; |
113 | } |
114 | |
115 | bool isNull() const noexcept |
116 | { |
117 | return !d; |
118 | } |
119 | |
120 | void reset(T *other = nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval<T *>()))) |
121 | { |
122 | if (d == other) |
123 | return; |
124 | T *oldD = std::exchange(d, other); |
125 | Cleanup::cleanup(oldD); |
126 | } |
127 | |
128 | #if QT_DEPRECATED_SINCE(6, 1)(((6<<16)|(1<<8)|(0)) > 0x050E00) |
129 | QT_DEPRECATED_VERSION_X_6_1("Use std::unique_ptr instead, and call release().") |
130 | T *take() noexcept |
131 | { |
132 | T *oldD = std::exchange(d, nullptr); |
133 | return oldD; |
134 | } |
135 | #endif |
136 | |
137 | #if QT_DEPRECATED_SINCE(6, 2)(((6<<16)|(2<<8)|(0)) > 0x050E00) |
138 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedPointer.") |
139 | void swap(QScopedPointer<T, Cleanup> &other) noexcept |
140 | { |
141 | qt_ptr_swap(d, other.d); |
142 | } |
143 | #endif |
144 | |
145 | typedef T *pointer; |
146 | |
147 | friend bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept |
148 | { |
149 | return lhs.data() == rhs.data(); |
150 | } |
151 | |
152 | friend bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept |
153 | { |
154 | return lhs.data() != rhs.data(); |
155 | } |
156 | |
157 | friend bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept |
158 | { |
159 | return lhs.isNull(); |
160 | } |
161 | |
162 | friend bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept |
163 | { |
164 | return rhs.isNull(); |
165 | } |
166 | |
167 | friend bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept |
168 | { |
169 | return !lhs.isNull(); |
170 | } |
171 | |
172 | friend bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept |
173 | { |
174 | return !rhs.isNull(); |
175 | } |
176 | |
177 | #if QT_DEPRECATED_SINCE(6, 2)(((6<<16)|(2<<8)|(0)) > 0x050E00) |
178 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedPointer.") |
179 | friend void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) noexcept |
180 | { p1.swap(p2); } |
181 | #endif |
182 | |
183 | protected: |
184 | T *d; |
185 | |
186 | private: |
187 | Q_DISABLE_COPY_MOVE(QScopedPointer)QScopedPointer(const QScopedPointer &) = delete; QScopedPointer &operator=(const QScopedPointer &) = delete; QScopedPointer (QScopedPointer &&) = delete; QScopedPointer &operator =(QScopedPointer &&) = delete; |
188 | }; |
189 | |
190 | template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> > |
191 | class QScopedArrayPointer : public QScopedPointer<T, Cleanup> |
192 | { |
193 | template <typename Ptr> |
194 | using if_same_type = typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, Ptr>::value, bool>::type; |
195 | public: |
196 | Q_NODISCARD_CTOR[[nodiscard]] |
197 | inline QScopedArrayPointer() : QScopedPointer<T, Cleanup>(nullptr) {} |
198 | inline ~QScopedArrayPointer() = default; |
199 | |
200 | template <typename D, if_same_type<D> = true> |
201 | Q_NODISCARD_CTOR[[nodiscard]] |
202 | explicit QScopedArrayPointer(D *p) |
203 | : QScopedPointer<T, Cleanup>(p) |
204 | { |
205 | } |
206 | |
207 | T &operator[](qsizetype i) |
208 | { |
209 | return this->d[i]; |
210 | } |
211 | |
212 | const T &operator[](qsizetype i) const |
213 | { |
214 | return this->d[i]; |
215 | } |
216 | |
217 | #if QT_DEPRECATED_SINCE(6, 2)(((6<<16)|(2<<8)|(0)) > 0x050E00) |
218 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedArrayPointer.") |
219 | void swap(QScopedArrayPointer &other) noexcept // prevent QScopedPointer <->QScopedArrayPointer swaps |
220 | { QScopedPointer<T, Cleanup>::swap(other); } |
221 | #endif |
222 | |
223 | private: |
224 | explicit inline QScopedArrayPointer(void *) |
225 | { |
226 | // Enforce the same type. |
227 | |
228 | // If you get a compile error here, make sure you declare |
229 | // QScopedArrayPointer with the same template type as you pass to the |
230 | // constructor. See also the QScopedPointer documentation. |
231 | |
232 | // Storing a scalar array as a pointer to a different type is not |
233 | // allowed and results in undefined behavior. |
234 | } |
235 | |
236 | Q_DISABLE_COPY_MOVE(QScopedArrayPointer)QScopedArrayPointer(const QScopedArrayPointer &) = delete ; QScopedArrayPointer &operator=(const QScopedArrayPointer &) = delete; QScopedArrayPointer(QScopedArrayPointer && ) = delete; QScopedArrayPointer &operator=(QScopedArrayPointer &&) = delete; |
237 | }; |
238 | |
239 | #if QT_DEPRECATED_SINCE(6, 2)(((6<<16)|(2<<8)|(0)) > 0x050E00) |
240 | template <typename T, typename Cleanup> |
241 | QT_DEPRECATED_VERSION_X_6_2("Use std::unique_ptr instead of QScopedArrayPointer.") |
242 | inline void swap(QScopedArrayPointer<T, Cleanup> &lhs, QScopedArrayPointer<T, Cleanup> &rhs) noexcept |
243 | { lhs.swap(rhs); } |
244 | #endif |
245 | |
246 | QT_END_NAMESPACE |
247 | |
248 | #endif // QSCOPEDPOINTER_H |