/** * @RDE_HEADER@ * $Id$ * $HeadURL$ * $Author$ */ #pragma once #include #include #include "symbology_xml_export.h" #include "symbol_types.h" /** \brief Cache for PixmapSymbols @author Stephan Kuhagen */ class QImage; class QColor; class QSize; class QGraphicsScene; namespace SymbologyXML { class Symbol; class SymbolTable; class SYMBOLOGY_XML_EXPORT PixmapSymbolCache : public QObject { Q_OBJECT public: ~PixmapSymbolCache(); //! Return a reference to this singleton static QSharedPointer instance(); //! Init the SymbolTables for attribute-symbols, takes ownership void setSymbolTables(SymbolTable *frames, SymbolTable *mobility, SymbolTable *bcdab, SymbolTable *commandLevel, SymbolTable *branches, SymbolTable *vehicle, SymbolTable *intrinsicMobility, SymbolTable *arming, SymbolTable *misc, SymbolTable *addOnSymbole, SymbolTable *sectorIcon ); bool symbolTablesAlreadySet() const { return _frames != nullptr; } // should be enough //! Enum to select different types of sub-caches // Enum-Order is chosen after size of bounding box enum CacheType { CacheMainSymbols, CacheFrames, CacheCommandLevel, CacheBranches, CacheVehicle, // ??? Position im enum richtig? CacheIntrinsicMobility, // ??? Position im enum richtig? CacheArming, // ??? Position im enum richtig? CacheMisc, // ??? Position im enum richtig? CacheAddOn, // ??? Position im enum richtig? CacheSectorIcon, // ??? Position im enum richtig? CacheMobility, CacheBCDAB, CacheFullSymbols, CacheAny }; /** Retrieve a pixmap representation for a symbol. If possible, get it from the cache, otherwise it is rendered on demand. If updateCache is false, a newly generated pixmap is not stored into the cache. This may be useful, if the symbol is known to be rendered only once. In this case, the caller is responsible for deleting the pixmap after use. Normally the cache has ownership of the pixmaps and deletes them according to the cache-strategy. If a pixmap is already in the cache, the pixmap is still owned by the cache, and the caller must not delete the pixmap. To check, if a pixmap is already in the cache, use contains(). \param symbol: The symbol to render \param additionalSymbolData: additional data to render (direction vector, fillStyle...) \param rgbaLine: The color for normal primitives. If rgbaRole is not valid, primitives are drawn black. \param rgbaRole: The color for filled areas. If rgbaRole is not valid, areas are not filled. \param size: The size of the pixmap. If the size is invalid (QSize()), the default size from the settings is used. NOTE: The given size does NOT set the actual size of the returned pixmap, but the pixel-size of the scene-square [-1.5, -1.5]-[1.5, 1.5]. This is the maximum bounding box of all frame-symbols. The main-symbol should always fit into this square, but some of the attributes will extend over these values, causing the returned pixmap to be greater than size. The pixmap is centered on the point [0, 0]. \param antiAliased: If true, create an antialiased version of the Symbol. \param overwriteAlpha: If this is true, the alpha-value (transparency) for lines and filled areas is taken from rgbaLine and rgbaRole. By default, it's taken from the global setting. \param updateCache: If this is false, the cache is not updated. \return QImage-pointer for the symbol. NOTE: Depending on updateCache, the caller is responsible for deleting the QImage after use. */ QImage getPixmap(const Symbol& symbol, const SymbolTypes::AdditionalSymbolData& additionalSymbolData, const QSize &size = QSize(), const QColor &rgbaLine = QColor(), const QColor &rgbaRole = QColor(), bool antiAliased = true, bool overwriteAlpha = false, bool updateCache = true); QImage getComponentPixmap(const Symbol& symbol, CacheType cacheType, const SymbolTypes::AdditionalSymbolData& additionalSymbolData, const QSize &size = QSize(), const QColor &rgbaLine = QColor(), const QColor &rgbaRole = QColor(), bool antiAliased = true, bool overwriteAlpha = false); //! Check, if this Symbol/value-combination is in the cache. See getPixmap(). bool contains(const Symbol& symbol, const SymbolTypes::AdditionalSymbolData& additionalSymbolData, const QSize &size = QSize(), const QColor &rgbaLine = QColor(), const QColor &rgbaRole = QColor(), bool antiAliased = true, bool overwriteAlpha = false); /** Clear the cache. Normally only the cache for full rendered symbols is cleared, because attribute-symbols do not change often. \param cacheType: Which cache to clear. If CacheAny is gives, all caches are cleared. */ void clearCache(CacheType cacheType = CacheFullSymbols); /** Dump all cached Pixmaps into files in a given directory. The filenames are creates as follows: PREFIXID_KEY.png PREFIX: parameter prefix ID: SymbolID KEY: Cache-Index-Key \param path: Directory where to dump the files. \param prefix: Prefix for filenames \param cacheType: Which cache to dump. */ void dumpCache(const QString &path, const QString &prefix = QString(), CacheType cacheType = CacheFullSymbols); //! Return number of full rendered cached symbol pixmaps unsigned int count() const { return _cacheFullSymbols.count(); } unsigned int size() const { return _cacheFullSymbols.size(); } //! Set global default for alpha-value of filled areas bool setAlphaFill(int alpha); int alphaFill() const { return _alphaFill; } //! Set global default for alpha-value of lines bool setAlphaLine(int alpha); int alphaLine() const { return _alphaLine; } //! Set global default for filling of areas bool setFilledRendering(SymbolTypes::t_filltype fillType); SymbolTypes::t_filltype getFilledRendering() const { return _fillType; } //! Set default size for Pixmaps bool setDefaultSize(const QSize &size); QSize getDefaultSize() const { return _defaultSize; } //! move all QObject derived members to thread t void moveToThread(QThread *t); //! set ID if there are multiple parallel caches: void setId(int id); //! get ID int id() const; protected: //! Create a KeyValue for Symbol-Caches QByteArray createKey(const Symbol &symbol, const SymbolTypes::AdditionalSymbolData &additionalSymbolData, const QSize &size, const QColor &rgbaLine, const QColor &rgbaRole, bool antiAliased); //! Check, if thZ/src/libsymbol_gui/pixmapSymbolCache.his Symbol/value-combination is in the cache. See getPixmap(). bool containsInternal(const Symbol& symbol, const SymbolTypes::AdditionalSymbolData& additionalSymbolData, const QSize &size, const QColor &rgbaLine, const QColor &rgbaRole, bool antiAliased, CacheType cacheType); //! Create a Pixmap and store to cache(s) QImage createPixmap(const Symbol& symbol, const SymbolTypes::AdditionalSymbolData& additionalSymbolData, const QSize &size, const QColor &rgbaLine, const QColor &rgbaRole, bool antiAliased, bool updateCache); private: PixmapSymbolCache(); SymbolTable *_frames{nullptr}; SymbolTable *_mobility{nullptr}; SymbolTable *_bcdab{nullptr}; SymbolTable *_commandLevel{nullptr}; SymbolTable *_branches{nullptr}; SymbolTable *_vehicle{nullptr}; SymbolTable *_intrinsicMobility{nullptr}; SymbolTable *_arming{nullptr}; SymbolTable *_misc{nullptr}; SymbolTable *_addOn{nullptr}; SymbolTable *_sectorIcon{nullptr}; QByteArray _lastKey; /** Bounding Boxes for Scenes (SceneRect): FullSymbols: -2.0, -2.0 -- 2.0, 2.0 MainSymbols: -1.5, -1.5 -- 1.5, 1.5 Frames: -2.0, -2.0 -- 2.0, 2.0 Mobility: -2.0, -2.0 -- 2.0, 2.0 BCDAB: -2.0, -2.0 -- 2.0, 2.0 CommandLevel: -1.5, -1.5 -- 1.5, 1.5 Branches: -1.5, -1.5 -- 1.5, 1.5 vehicle:? -1.5, -1.5 -- 1.5, 1.5 ??? intrinsicMob:?-1.5, -1.5 -- 1.5, 1.5 ??? arming: ? -1.5, -1.5 -- 1.5, 1.5 ??? */ QCache _cacheFullSymbols; /* 1000 */ QCache _cacheMainSymbols; /* 1000 */ QCache _cacheFrames; /* 500 */ QCache _cacheMobility; /* 500 */ QCache _cacheBCDAB; /* 500 */ QCache _cacheCommandLevel; /* 500 */ QCache _cacheBranches; /* 500 */ QCache _cacheVehicle; /* 50 */ QCache _cacheIntrinsicMobility; /* 50 */ QCache _cacheArming; /* 50 */ QCache _cacheMisc; /* 500 */ QCache _cacheAddOn; /* 10 */ QCache _cacheSectorIcon; /* 100 */ int _alphaFill{255}; int _alphaLine{255}; SymbolTypes::t_filltype _fillType{SymbolTypes::FILLTYPE_FILLED}; QSize _defaultSize{128, 128}; QGraphicsScene *_scene{nullptr}; int _id; }; // class PixmapSymbol } // namespace SymbologyXML