File indexing completed on 2024-05-19 04:26:21

0001 /*
0002  *  SPDX-FileCopyrightText: 2015 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef __KIS_LOD_CAPABLE_LAYER_OFFSET_H
0008 #define __KIS_LOD_CAPABLE_LAYER_OFFSET_H
0009 
0010 #include <QScopedPointer>
0011 #include "kritaimage_export.h"
0012 #include "kis_default_bounds_base.h"
0013 
0014 
0015 namespace KisLodSwitchingWrapperDetail
0016 {
0017 /**
0018  * By default forward the syncing request to the wrapped
0019  * object itself.
0020  */
0021 template <typename T>
0022 inline T syncLodNValue(const T &value, int lod) {
0023     return value.syncLodNValue(lod);
0024 }
0025 
0026 /**
0027  * Otherwise just use specialized functions for that
0028  */
0029 KRITAIMAGE_EXPORT
0030 QPoint syncLodNValue(const QPoint &value, int lod);
0031 
0032 } // namespace KisLodSwitchingWrapperDetail
0033 
0034 template <typename T>
0035 class KisLodSwitchingWrapper
0036 {
0037 public:
0038     KisLodSwitchingWrapper(T &&initialValue, KisDefaultBoundsBaseSP defaultBounds)
0039         : m_defaultBounds(defaultBounds),
0040           m_data(std::forward<T>(initialValue)),
0041           m_lodNData(KisLodSwitchingWrapperDetail::syncLodNValue(m_data, defaultBounds->currentLevelOfDetail()))
0042     {
0043     }
0044 
0045     KisLodSwitchingWrapper(KisDefaultBoundsBaseSP defaultBounds)
0046         : m_defaultBounds(defaultBounds)
0047     {
0048     }
0049 
0050     KisLodSwitchingWrapper(const KisLodSwitchingWrapper &rhs)
0051         : m_defaultBounds(rhs.m_defaultBounds)
0052         , m_data(rhs.m_data)
0053         , m_lodNData(rhs.m_lodNData)
0054     {
0055     }
0056 
0057     KisLodSwitchingWrapper& operator=(const KisLodSwitchingWrapper &rhs)
0058     {
0059         if (this != &rhs) {
0060             m_defaultBounds = rhs.m_defaultBounds;
0061             m_data = rhs.m_data;
0062             m_lodNData = rhs.m_lodNData;
0063         }
0064 
0065         return *this;
0066     }
0067 
0068 
0069     KisDefaultBoundsBaseSP defaultBounds() const {
0070         return m_defaultBounds;
0071     }
0072 
0073     void setDefaultBounds(KisDefaultBoundsBaseSP defaultBounds) {
0074         m_defaultBounds = defaultBounds;
0075     }
0076 
0077     const T *operator->() const noexcept
0078     {
0079         return m_defaultBounds->currentLevelOfDetail() > 0 ? &m_lodNData : &m_data;
0080     }
0081 
0082     T *operator->() noexcept
0083     {
0084         return m_defaultBounds->currentLevelOfDetail() > 0 ? &m_lodNData : &m_data;
0085     }
0086 
0087     const T& operator*() const noexcept
0088     {
0089         return m_defaultBounds->currentLevelOfDetail() > 0 ? m_lodNData : m_data;
0090     }
0091 
0092     T& operator*() noexcept
0093     {
0094         return m_defaultBounds->currentLevelOfDetail() > 0 ? m_lodNData : m_data;
0095     }
0096 
0097     void syncLodCache() {
0098         m_lodNData =
0099             KisLodSwitchingWrapperDetail::syncLodNValue(
0100                 m_data, m_defaultBounds->currentLevelOfDetail());
0101     }
0102 
0103     using LodState = std::pair<int, T>;
0104 
0105     void setLodState(const LodState &state) {
0106         (state.first > 0 ? m_lodNData : m_data) = state.second;
0107     }
0108 
0109     LodState lodState() const {
0110         return std::make_pair(m_defaultBounds->currentLevelOfDetail(), *(*this));
0111     }
0112 
0113     operator LodState() const {
0114         return lodState();
0115     }
0116 
0117     KisLodSwitchingWrapper& operator=(const LodState &rhs)
0118     {
0119         setLodState(rhs);
0120         return *this;
0121     }
0122 
0123 
0124 private:
0125     KisDefaultBoundsBaseSP m_defaultBounds;
0126     T m_data;
0127     T m_lodNData;
0128 };
0129 
0130 using KisLodCapableLayerOffset = KisLodSwitchingWrapper<QPoint>;
0131 
0132 #endif /* __KIS_LOD_CAPABLE_LAYER_OFFSET_H */