File indexing completed on 2024-05-12 15:59:55

0001 /*
0002  *  SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef KORESOURCECACHEINTERFACE_H
0008 #define KORESOURCECACHEINTERFACE_H
0009 
0010 #include "kritaresources_export.h"
0011 
0012 #include <QSharedPointer>
0013 
0014 class QString;
0015 class QVariant;
0016 
0017 
0018 /**
0019  * @brief a provider-like interface class for sharing caches between multiple resources
0020  *
0021  * Some resources, e.g. KisPaintOpPreset, may require some computational-
0022  * intensive work to be done to start being useful. This work is not
0023  * serialized into the file format, so after we load the preset and
0024  * before we can start using it we need to spend some time on regenerating
0025  * some caches. For KisPaintOpPreset such caches are: KisQImagePyramid
0026  * and outline.
0027  *
0028  * Instead of generating this cache before every stroke we can
0029  * pregenerate it in advance and share among multiple presets.
0030  *
0031  * And here comes KoResourceCacheInterface. It provides abstract
0032  * interface for creating a cache and passing it into other presets.
0033  *
0034  * Usage:
0035  *
0036  *        \code{.cpp}
0037  *
0038  *        // in the GUI thread
0039  *        KisPaintOpPresetSP tempPreset =
0040  *            preset->cloneWithResourcesSnapshot(resourcesInterface, canvasResourcesInterface);
0041  *
0042  *        // in the non-GUI background thread [1]
0043  *        KoResourceCacheInterfaceSP cacheInterface =
0044  *           new KoResourceCacheStorage();
0045  *        tempPreset->regenerateResourceCache(cacheInterface);
0046  *
0047  *        // back in the GUI thread [2]
0048  *        preset->setResourceCacheInterface(cacheInterface);
0049  *
0050  *        // now the GUI-scope preset has all the caches prepared,
0051  *        // therefore, when we clone it to do real painting, it
0052  *        // will have all the caches ready
0053  *
0054  *        \endcode
0055  *
0056  * [1] - please take it into account that we cannot access the original
0057  *       `preset` from the non-GUI thread, because it may require resource
0058  *       database access, which is impossible in non-GUI thread. Therefore
0059  *       we must first create a copy of this resource with all the external
0060  *       resources linked to it, and only after that pass it to the non-gui
0061  *       thread
0062  *
0063  * [2] - there is also a cache-validity complication. We have generated the
0064  *       cache using a snapshot of a specific state of `resourcesInterface` and
0065  *       `canvasResourcesInterface`. Therefore, if any of these change, we
0066  *       must reset the cache manually! See code in KisPresetShadowUpdater
0067  *       for example implementation.
0068  *
0069  */
0070 class KRITARESOURCES_EXPORT KoResourceCacheInterface
0071 {
0072 public:
0073     virtual ~KoResourceCacheInterface();
0074 
0075     /// fetch a cached object from the cache using \p key
0076     virtual QVariant fetch(const QString &key) const = 0;
0077 
0078     /// store a cached object \p value into the cache using \p key
0079     /// WARNING: storing an object twice with the same \p key is
0080     ///          considered as invalid operation and will assert!
0081     ///          This behavior is intentional to avoid cache key
0082     ///          aliasing.
0083     virtual void put(const QString &key, const QVariant &value) = 0;
0084 
0085     /**
0086      * A special cookie the resource may (or may not) initialize
0087      * while initializing the cache. The resource may use this cookie
0088      * later to verify that this resource actually belongs this
0089      * very resource, not some other resource.
0090      */
0091     using RelatedResourceCookie = std::uintptr_t;
0092 
0093     /**
0094      * Sets the related resource cookie
0095      *
0096      * \see RelatedResourceCookie
0097      */
0098     void setRelatedResourceCookie(RelatedResourceCookie cookie);
0099 
0100     /**
0101      * Returns the related resource cookie
0102      *
0103      * \see RelatedResourceCookie
0104      */
0105     RelatedResourceCookie relatedResourceCookie() const;
0106 
0107 private:
0108     RelatedResourceCookie m_cookie = RelatedResourceCookie();
0109 };
0110 
0111 using KoResourceCacheInterfaceSP = QSharedPointer<KoResourceCacheInterface>;
0112 
0113 Q_DECLARE_METATYPE(KoResourceCacheInterfaceSP)
0114 
0115 #endif // KORESOURCECACHEINTERFACE_H