/** * @RDE_HEADER@ * $Id$ * $HeadURL$ * $Author$ */ #include "pixmap_symbol_cache.h" #include "symbol_exporter.h" #include "symbol_table.h" #include #include #include #include #include namespace SymbologyXML { static const QImage::Format ImageFormat = QImage::Format_ARGB32; //----------------------------------------------------------------------------- QSharedPointer PixmapSymbolCache::instance() { static QWeakPointer psc; auto sp(psc.lock()); if (sp) return sp; sp.reset(new PixmapSymbolCache); psc = sp; return sp; } // PixmapSymbolCache* PixmapSymbolCache::instance() static inline void setNew(SymbolTable *&member, SymbolTable *newValue) { if (member == newValue) return; delete member; member = newValue; } void PixmapSymbolCache::setSymbolTables(SymbolTable *frames, SymbolTable *mobility, SymbolTable *bcdab, SymbolTable *commandLevel, SymbolTable *branches, SymbolTable *vehicle, SymbolTable *intrinsicMobility, SymbolTable *arming, SymbolTable *misc, SymbolTable *addOnSymbole, SymbolTable *sectorIcon) { setNew(_frames , frames); setNew(_mobility , mobility); setNew(_bcdab , bcdab); setNew(_commandLevel , commandLevel); setNew(_branches , branches); setNew(_vehicle , vehicle); setNew(_intrinsicMobility, intrinsicMobility); setNew(_arming , arming); setNew(_misc , misc); setNew(_addOn , addOnSymbole); setNew(_sectorIcon , sectorIcon); clearCache(CacheAny); } // void PixmapSymbolCache::setSymbolTables(SymbolTable *frames... QImage PixmapSymbolCache::getPixmap(const Symbol& symbol, const SymbolTypes::AdditionalSymbolData& additionalSymbolData, const QSize &size, const QColor &rgbaLine, const QColor &rgbaRole, bool antiAliased, bool overwriteAlpha, bool updateCache) { QSize localSize = ( size.isValid() && !size.isNull() ) ? size : _defaultSize; QColor rgbaLineLocal = rgbaLine; QColor rgbaRoleLocal = rgbaRole; if ( ! overwriteAlpha ) { rgbaLineLocal.setAlpha(_alphaLine); rgbaRoleLocal.setAlpha(_alphaFill); } const auto key = createKey(symbol, additionalSymbolData, localSize, rgbaLineLocal, rgbaRoleLocal, antiAliased); QImage *img = _cacheFullSymbols[key]; if (img) return *img; return createPixmap(symbol, additionalSymbolData, localSize, rgbaLineLocal, rgbaRoleLocal, antiAliased, updateCache); } // QImage* PixmapSymbolCache::getPixmap(const Symbol... QImage PixmapSymbolCache::getComponentPixmap(const Symbol& symbol, CacheType cacheType, const SymbolTypes::AdditionalSymbolData& additionalSymbolData, const QSize &size, const QColor &rgbaLine, const QColor &rgbaRole, bool antiAliased, bool overwriteAlpha) { QSize localSize = ( size.isValid() && !size.isNull() ) ? size : _defaultSize; QColor rgbaLineLocal = rgbaLine; QColor rgbaRoleLocal = rgbaRole; if ( !overwriteAlpha ) { rgbaLineLocal.setAlpha(_alphaLine); rgbaRoleLocal.setAlpha(_alphaFill); } if (!containsInternal(symbol, additionalSymbolData, localSize, rgbaLineLocal, rgbaRoleLocal, antiAliased, cacheType) ) createPixmap(symbol, additionalSymbolData, localSize, rgbaLineLocal, rgbaRoleLocal, antiAliased, true ); switch (cacheType) { case CacheAny : case CacheFullSymbols : return *_cacheFullSymbols[_lastKey]; case CacheMainSymbols : return *_cacheMainSymbols[_lastKey]; case CacheFrames : return *_cacheFrames[_lastKey]; case CacheMobility : return *_cacheMobility[_lastKey]; case CacheBCDAB : return *_cacheBCDAB[_lastKey]; case CacheCommandLevel : return *_cacheCommandLevel[_lastKey]; case CacheBranches : return *_cacheBranches[_lastKey]; case CacheVehicle : return *_cacheVehicle[_lastKey]; case CacheIntrinsicMobility: return *_cacheIntrinsicMobility[_lastKey]; case CacheArming : return *_cacheArming[_lastKey]; case CacheMisc : return *_cacheMisc[_lastKey]; case CacheAddOn : return *_cacheAddOn[_lastKey]; case CacheSectorIcon : return *_cacheSectorIcon[_lastKey]; } return QImage(); } // QImage PixmapSymbolCache::getComponentPixmap(const Symbol... bool PixmapSymbolCache::contains(const Symbol& symbol, const SymbolTypes::AdditionalSymbolData& additionalSymbolData, const QSize &size, const QColor &rgbaLine, const QColor &rgbaRole, bool antiAliased, bool overwriteAlpha) { QColor rgbaLineLocal = rgbaLine; QColor rgbaRoleLocal = rgbaRole; if ( ! overwriteAlpha ) { rgbaLineLocal.setAlpha(_alphaLine); rgbaRoleLocal.setAlpha(_alphaFill); } return containsInternal(symbol, additionalSymbolData, size, rgbaLineLocal, rgbaRoleLocal, antiAliased, CacheFullSymbols); } // bool PixmapSymbolCache::contains(const Symbol& symbol... void PixmapSymbolCache::clearCache(CacheType cacheType) { switch (cacheType) { case CacheFullSymbols: _cacheFullSymbols.clear(); break; case CacheMainSymbols: _cacheMainSymbols.clear(); break; case CacheFrames: _cacheFrames.clear(); break; case CacheMobility: _cacheMobility.clear(); break; case CacheBCDAB: _cacheBCDAB.clear(); break; case CacheCommandLevel: _cacheCommandLevel.clear(); break; case CacheBranches: _cacheBranches.clear(); break; case CacheVehicle: _cacheVehicle.clear(); break; case CacheIntrinsicMobility: _cacheIntrinsicMobility.clear(); break; case CacheArming: _cacheArming.clear(); break; case CacheMisc: _cacheMisc.clear(); break; case CacheAddOn: _cacheAddOn.clear(); break; case CacheSectorIcon: _cacheSectorIcon.clear(); break; case CacheAny: _cacheFullSymbols.clear(); _cacheMainSymbols.clear(); _cacheFrames.clear(); _cacheMobility.clear(); _cacheBCDAB.clear(); _cacheCommandLevel.clear(); _cacheBranches.clear(); _cacheVehicle.clear(); _cacheIntrinsicMobility.clear(); _cacheArming.clear(); _cacheMisc.clear(); _cacheAddOn.clear(); _cacheSectorIcon.clear(); break; } } // void PixmapSymbolCache::clearCache(bool fullSymbols... void PixmapSymbolCache::dumpCache(const QString &path, const QString &prefix, CacheType cacheType) { QCache *cache; switch (cacheType) { case CacheFullSymbols: cache = &_cacheFullSymbols; break; case CacheMainSymbols: cache = &_cacheMainSymbols; break; case CacheFrames: cache = &_cacheFrames; break; case CacheMobility: cache = &_cacheMobility; break; case CacheBCDAB: cache = &_cacheBCDAB; break; case CacheCommandLevel: cache = &_cacheCommandLevel; break; case CacheBranches: cache = &_cacheBranches; break; case CacheVehicle: cache = &_cacheVehicle; break; case CacheIntrinsicMobility: cache = &_cacheIntrinsicMobility; break; case CacheArming: cache = &_cacheArming; break; case CacheMisc: cache = &_cacheMisc; break; case CacheAddOn: cache = &_cacheAddOn; break; case CacheSectorIcon: cache = &_cacheSectorIcon; break; case CacheAny: dumpCache(path, prefix, CacheFullSymbols); dumpCache(path, prefix, CacheMainSymbols); dumpCache(path, prefix, CacheFrames); dumpCache(path, prefix, CacheMobility); dumpCache(path, prefix, CacheBCDAB); dumpCache(path, prefix, CacheCommandLevel); dumpCache(path, prefix, CacheBranches); dumpCache(path, prefix, CacheVehicle); dumpCache(path, prefix, CacheIntrinsicMobility); dumpCache(path, prefix, CacheArming); dumpCache(path, prefix, CacheMisc); dumpCache(path, prefix, CacheAddOn); dumpCache(path, prefix, CacheSectorIcon); return; default: return; } const auto cacheKeys = cache->keys(); for (const auto &key : cacheKeys) { QString fileName = QStringLiteral("%1/%2%3.png").arg(prefix, QString::fromLatin1(key)); cache->object(key)->save( fileName ); } } // void PixmapSymbolCache::dumpCache(const QString path, ... bool PixmapSymbolCache::setAlphaFill(int alpha) { if ( (alpha >= 0) && (alpha <= 255) ) { if (_alphaFill != alpha) { _alphaFill = alpha; this->clearCache(CacheAny); } return true; } else { return false; } } // bool PixmapSymbolCache::setAlphaFill(int alpha) bool PixmapSymbolCache::setAlphaLine(int alpha) { if ( (alpha >= 0) && (alpha <= 255) ) { if (_alphaLine != alpha) { _alphaLine = alpha; this->clearCache(CacheAny); } return true; } else { return false; } } // bool PixmapSymbolCache::setAlphaLine(int alpha) bool PixmapSymbolCache::setFilledRendering(SymbolTypes::t_filltype fillType) { bool changed = false; if ( fillType != SymbolTypes::FILLTYPE_UNDEFINED ) { if (_fillType != fillType) { _fillType = fillType; this->clearCache(CacheAny); changed = true; } } return changed; } // void PixmapSymbolCache::setFilledRendering(FillType fill) bool PixmapSymbolCache::setDefaultSize(const QSize &size) { if (!size.isValid()) return false; _defaultSize = size; return true; } // bool PixmapSymbolCache::setDefaultSize(QSize size) QByteArray PixmapSymbolCache::createKey(const Symbol &symbol, const SymbolTypes::AdditionalSymbolData &additionalSymbolData, const QSize &size, const QColor &rgbaLine, const QColor &rgbaRole, bool antiAliased) { QByteArray key(512, Qt::Uninitialized); const int len = snprintf(key.data(), key.size(), "%d-%s-%d-%d-%d-%d-%lld-%d-%d-%d-%d-%s-%d-%d-%d-%d-%d-%lld-%d-%d-%d", symbol._id, additionalSymbolData.createKey().constData(), size.width(), size.height(), rgbaLine.rgba(), rgbaRole.rgba(), symbol._branchTags(), symbol._dimen, symbol._affil, symbol._bcd_ab, symbol._commandlevel, (symbol.getHeadquarter() ? "1" : "0"), symbol._mob, symbol._vehicle, symbol._intrinsicmob, symbol._arming, symbol._sectoricon, symbol._miscTags(), symbol._primitives.count(), symbol._changeCount, antiAliased); key.resize(len); // does proper \0 termination // if ( fill == DefaultFill ) { // keyList << QByteArray::number(_fillType); // } else { // keyList << QByteArray::number(fill); // } // keyList << QByteArray::number(fill); _lastKey = key; return key; } // QByteArray PixmapSymbolCache::createKey(const Symbol& symbol... bool PixmapSymbolCache::containsInternal(const Symbol& symbol, const SymbolTypes::AdditionalSymbolData& additionalSymbolData, const QSize &size, const QColor &rgbaLine, const QColor &rgbaRole, bool antiAliased, CacheType cacheType) { const auto key = createKey(symbol, additionalSymbolData, size, rgbaLine, rgbaRole, antiAliased); switch (cacheType) { case CacheFullSymbols: return _cacheFullSymbols.contains(key); case CacheMainSymbols: return _cacheMainSymbols.contains(key); case CacheFrames: return _cacheFrames.contains(key); case CacheMobility: return _cacheMobility.contains(key); case CacheBCDAB: return _cacheBCDAB.contains(key); case CacheCommandLevel: return _cacheCommandLevel.contains(key); case CacheBranches: return _cacheBranches.contains(key); case CacheVehicle: return _cacheVehicle.contains(key); case CacheIntrinsicMobility: return _cacheIntrinsicMobility.contains(key); case CacheArming: return _cacheArming.contains(key); case CacheMisc: return _cacheMisc.contains(key); case CacheAddOn: return _cacheAddOn.contains(key); case CacheSectorIcon: return _cacheSectorIcon.contains(key); case CacheAny: return _cacheFullSymbols.contains(key) || _cacheMainSymbols.contains(key) || _cacheFrames.contains(key) || _cacheMobility.contains(key) || _cacheBCDAB.contains(key) || _cacheCommandLevel.contains(key) || _cacheBranches.contains(key) || _cacheVehicle.contains(key) || _cacheIntrinsicMobility.contains(key) || _cacheArming.contains(key) || _cacheAddOn.contains(key) || _cacheSectorIcon.contains(key) || _cacheMisc.contains(key); } return false; } // bool PixmapSymbolCache::containsInternal(const Symbol& symbol... QImage PixmapSymbolCache::createPixmap(const Symbol& symbol, const SymbolTypes::AdditionalSymbolData& additionalSymbolData, const QSize &size, const QColor &rgbaLine, const QColor &rgbaRole, bool antiAliased, bool updateCache) { static const QRectF smallBox(-1.5, -1.5, 3.0, 3.0); static const QRectF bigBox (-2.0, -2.0, 4.0, 4.0); //QColor transpWhite(255, 255, 255, 0); SymbolTypes::t_symbolTableCont symTableCont; symTableCont.resize(SymbolTypes::ICON_TYPE_END); symTableCont[SymbolTypes::ICON_TYPE_SECTOR_ICON] = _sectorIcon; symTableCont[SymbolTypes::ICON_TYPE_INTRINSIC_MOBILITY] = _intrinsicMobility; symTableCont[SymbolTypes::ICON_TYPE_VEHICLE] = _vehicle; symTableCont[SymbolTypes::ICON_TYPE_ARMING] = _arming; symTableCont[SymbolTypes::ICON_TYPE_MISC] = _misc; // Draw symbols with small bbox first _scene->setSceneRect(smallBox); SymbolTypes::AdditionalSymbolData l_additionalSymbolData; ///////////////////////////////////////////////////////////////////////////// // Main Symbol ///////////////////////////////////////////////////////////////////////////// const auto mainKey = createKey(symbol, l_additionalSymbolData, size, rgbaLine, rgbaLine, antiAliased); QImage *pmSymbolMain = _cacheMainSymbols[mainKey]; if (!pmSymbolMain) { pmSymbolMain = new QImage(size, ImageFormat); #if defined (SYMBOL_TEXT_IN_BLACK) && (SYMBOL_TEXT_IN_BLACK == 1) // RATC: QColor bg = Qt::black; // Ansonsten würde die z.T. schwarze Schrift rot 'verschmiert' werden :-( // Nun wird rot zwar leicht mit schwarz 'verschmiert', was aber nicht wirklich auffaellt. #else // TES-UAE: QColor bg = rgbaLine; #endif // #if defined (SYMBOL_TEXT_IN_BLACK)... bg.setAlpha(0); //pmSymbolMain->setColor(0, bg.rgba()); pmSymbolMain->fill(bg.rgba()); QPainter painter(pmSymbolMain); if (antiAliased) { painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); } _scene->clear(); SymbolExporter::drawSymbol(symbol, symTableCont, _scene, rgbaLine, rgbaLine, 0.0, false, antiAliased); _scene->render(&painter); painter.end(); // QString name = QString("/tmp/symbol_%1_%2.png").arg(symbol.id()).arg(rgbaLine.rgba()); // pmSymbolMain->save(name); _cacheMainSymbols.insert(mainKey, pmSymbolMain); } ///////////////////////////////////////////////////////////////////////////// // Vehicle-Symbol ///////////////////////////////////////////////////////////////////////////// QImage *pmSymbolVehicle = nullptr; if ( (symbol.getVehicle() != SymbolTypes::VEHICLE_UNDEFINED) && (_vehicle != nullptr) ) { const Symbol *symbolVehicle = _vehicle->value(SymbolTable::getVehicleSymbolID(symbol)); if (symbolVehicle) { const auto key = createKey(*symbolVehicle, l_additionalSymbolData, size, rgbaLine, rgbaLine, antiAliased); pmSymbolVehicle = _cacheVehicle[key]; if (!pmSymbolVehicle) { pmSymbolVehicle = new QImage(size, ImageFormat); QColor bg = rgbaLine; bg.setAlpha(0); //pmSymbolVehicle->setColor(0, bg.rgba()); pmSymbolVehicle->fill(bg.rgba()); QPainter painter(pmSymbolVehicle); if ( antiAliased ) { painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); } _scene->clear(); SymbolExporter::drawSymbol(*symbolVehicle, symTableCont, _scene, rgbaLine, rgbaLine, 0.0, true, antiAliased); _scene->render(&painter); _cacheVehicle.insert(key, pmSymbolVehicle); } } } ///////////////////////////////////////////////////////////////////////////// // Intrinsic-Mobility Symbol ///////////////////////////////////////////////////////////////////////////// QImage *pmSymbolIntrinsicMob = nullptr; if ( (symbol.getIntrinsicMob() != SymbolTypes::INTRINSICMOB_UNDEFINED) && (_intrinsicMobility != nullptr) ) { const Symbol *symbolIntrinsicMob = _intrinsicMobility->value(SymbolTable::getIntrinsicMobilitySymbolID(symbol)); if (symbolIntrinsicMob) { const auto key = createKey(*symbolIntrinsicMob, l_additionalSymbolData, size, rgbaLine, rgbaLine, antiAliased); pmSymbolIntrinsicMob = _cacheIntrinsicMobility[key]; if (!pmSymbolIntrinsicMob) { pmSymbolIntrinsicMob = new QImage(size, ImageFormat); QColor bg = rgbaLine; bg.setAlpha(0); //pmSymbolIntrinsicMob->setColor(0, bg.rgba()); pmSymbolIntrinsicMob->fill(bg.rgba()); QPainter painter(pmSymbolIntrinsicMob); if ( antiAliased ) { painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); } _scene->clear(); SymbolExporter::drawSymbol(*symbolIntrinsicMob, symTableCont, _scene, rgbaLine, rgbaLine, 0.0, true, antiAliased); _scene->render(&painter); _cacheIntrinsicMobility.insert(key, pmSymbolIntrinsicMob); } } } ///////////////////////////////////////////////////////////////////////////// // Arming-Symbol ///////////////////////////////////////////////////////////////////////////// QImage *pmSymbolArming = nullptr; if ( (symbol.getArming() != SymbolTypes::ARMING_UNDEFINED) && (_arming != nullptr) ) { const Symbol *symbolArming = _arming->value(SymbolTable::getArmingSymbolID(symbol)); if (symbolArming) { const auto key = createKey(*symbolArming, l_additionalSymbolData, size, rgbaLine, rgbaLine, antiAliased); pmSymbolArming = _cacheArming[key]; if (!pmSymbolArming) { pmSymbolArming = new QImage(size, ImageFormat); QColor bg = rgbaLine; bg.setAlpha(0); //pmSymbolArming->setColor(0, bg.rgba()); pmSymbolArming->fill(bg.rgba()); QPainter painter(pmSymbolArming); if ( antiAliased ) { painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); } _scene->clear(); SymbolExporter::drawSymbol(*symbolArming, symTableCont, _scene, rgbaLine, rgbaLine, 0.0, true, antiAliased); _scene->render(&painter); _cacheArming.insert(key, pmSymbolArming); } } } ///////////////////////////////////////////////////////////////////////////// // SectorIcon-Symbol ///////////////////////////////////////////////////////////////////////////// QImage *pmSymbolSectorIcon = nullptr; if ( (symbol.getSectorIcon() != SymbolTypes::SECICON_UNDEFINED) && (_sectorIcon != nullptr) ) { const Symbol *symbolSectorIcon = _sectorIcon->value(SymbolTable::getSectorIconSymbolID(symbol)); if (symbolSectorIcon) { const auto key = createKey(*symbolSectorIcon, l_additionalSymbolData, size, rgbaLine, rgbaLine, antiAliased); pmSymbolSectorIcon = _cacheSectorIcon[key]; if (!pmSymbolSectorIcon) { pmSymbolSectorIcon = new QImage(size, ImageFormat); QColor bg = rgbaLine; bg.setAlpha(0); //pmSymbolArming->setColor(0, bg.rgba()); pmSymbolSectorIcon->fill(bg.rgba()); QPainter painter(pmSymbolSectorIcon); if ( antiAliased ) { painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); } _scene->clear(); SymbolExporter::drawSymbol(*symbolSectorIcon, symTableCont, _scene, rgbaLine, rgbaLine, 0.0, true, antiAliased); _scene->render(&painter); _cacheSectorIcon.insert(key, pmSymbolSectorIcon); } } } ///////////////////////////////////////////////////////////////////////////// // Misc Symbols ///////////////////////////////////////////////////////////////////////////// QList pmSymbolMisc; if ( _misc != nullptr ) { for (unsigned int i = 0; i < symbol.getMiscTags().size(); ++i) { if ( symbol.getMiscTags().at(i) ) { const Symbol *symbolMiscTmp = _misc->value(SymbolTable::getMiscSymbolID((SymbolTypes::t_misc)i)); if (symbolMiscTmp) { Symbol symbolMisc(*symbolMiscTmp); symbolMisc.setDimen(symbol.getDimen()); symbolMisc.setAffil(symbol.getAffil()); // Derzeit keine Transformation // symbolMisc->transformSymbol(Symbol::TMG_BRANCHES, _misc); const auto key = createKey(symbolMisc, l_additionalSymbolData, size, rgbaLine, rgbaLine, antiAliased); auto cacheSymbolTmp = _cacheMisc[key]; if (cacheSymbolTmp) { pmSymbolMisc.append(cacheSymbolTmp); } else { QImage *btTmp = new QImage(size, ImageFormat); QColor bg = rgbaLine; bg.setAlpha(0); //btTmp->setColor(0, bg.rgba()); btTmp->fill(bg.rgba()); QPainter painter(btTmp); if ( antiAliased ) { painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); } _scene->clear(); SymbolExporter::drawSymbol(symbolMisc, symTableCont, _scene, rgbaLine, rgbaLine, 0.0, true, antiAliased); _scene->render(&painter); _cacheMisc.insert(key, btTmp); pmSymbolMisc.append(btTmp); } } } } } ///////////////////////////////////////////////////////////////////////////// // CommandLevel Symbol ///////////////////////////////////////////////////////////////////////////// QImage *pmSymbolCL = nullptr; if ( (symbol.getCommandLevel() != SymbolTypes::CL_UNDEFINED) && (_commandLevel != nullptr) ) { const Symbol *symbolCommandLevelTmp = _commandLevel->value(SymbolTable::getCommandLevelSymbolID(symbol)); if (symbolCommandLevelTmp) { Symbol symbolCL(*symbolCommandLevelTmp); symbolCL.setDimen(symbol.getDimen()); symbolCL.setAffil(symbol.getAffil()); symbolCL.transformSymbol(Symbol::TMG_COMMAND_LEVEL); const auto key = createKey(symbolCL, l_additionalSymbolData, size, rgbaLine, rgbaLine, antiAliased); pmSymbolCL = _cacheCommandLevel[key]; if (!pmSymbolCL) { pmSymbolCL = new QImage(size, ImageFormat); QColor bg = rgbaLine; bg.setAlpha(0); //pmSymbolCL->setColor(0, bg.rgba()); pmSymbolCL->fill(bg.rgba()); QPainter painter(pmSymbolCL); if ( antiAliased ) { painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); } _scene->clear(); SymbolExporter::drawSymbol(symbolCL, symTableCont, _scene, rgbaLine, rgbaLine, 0.0, false, // zwms_roleType outlined: filled prims in role color antiAliased); _scene->render(&painter); _cacheCommandLevel.insert(key, pmSymbolCL); } } } ///////////////////////////////////////////////////////////////////////////// // Branch/Truppengattung Symbols ///////////////////////////////////////////////////////////////////////////// QList pmSymbolBT; if ( _branches != nullptr ) { for (unsigned int i=0; ivalue(SymbolTable::getBranchSymbolID((SymbolTypes::t_branch)i)); if (symbolBTTmp) { Symbol symbolBT(*symbolBTTmp); // a) symbolBT bekommt Dimension vom (Gesamt-)symbol symbolBT.setDimen(symbol.getDimen()); // b) Affiliation wird nur bei FILLED oder OUTLINED uebernommen... if ( (_fillType == SymbolTypes::FILLTYPE_FILLED) || (_fillType == SymbolTypes::FILLTYPE_OUTLINED) ) { symbolBT.setAffil(symbol.getAffil()); } else { // ... bei NurIcon wird Affil=NEUTRAL genutzt, // damit z.B. die Texte 'dicht' am Symbol stehen KOENNTEN: // (Da die texte aber derzeit unabhaengig vom Affil positioniert werden..) symbolBT.setAffil(SymbolTypes::NEUTRAL); } symbolBT.transformSymbol(Symbol::TMG_BRANCHES, _branches); const auto key = createKey(symbolBT, l_additionalSymbolData, size, rgbaLine, rgbaLine, antiAliased); auto pmBranch = _cacheBranches[key]; if (pmBranch) { pmSymbolBT.append(pmBranch); } else { QImage *btTmp = new QImage(size, ImageFormat); QColor bg = rgbaLine; bg.setAlpha(0); //btTmp->setColor(0, bg.rgba()); btTmp->fill(bg.rgba()); QPainter painter(btTmp); if ( antiAliased ) { painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); } _scene->clear(); SymbolExporter::drawSymbol(symbolBT, symTableCont, _scene, rgbaLine, rgbaLine, 0.0, true, antiAliased); _scene->render(&painter); _cacheBranches.insert(key, btTmp); pmSymbolBT.append(btTmp); } } } } } ///////////////////////////////////////////////////////////////////////////// // Draw symbols with big bbox ///////////////////////////////////////////////////////////////////////////// _scene->setSceneRect(bigBox); const QSize pmSize(size * 4 / 3); ///////////////////////////////////////////////////////////////////////////// // Frame Symbol ///////////////////////////////////////////////////////////////////////////// // FrameSymbol nun in bigbox, um das Abschneiden der headquarter-linie zu vermeiden. QImage *pmSymbolFrame = nullptr; Symbol *symbolFrame = nullptr; // Wenn entweder eine frameSybol direkt erforderlich ist... if ( (_frames != nullptr) && ( (_fillType == SymbolTypes::FILLTYPE_FILLED) || (_fillType == SymbolTypes::FILLTYPE_OUTLINED) ) ) { auto tmp = _frames->value(SymbolTable::getFrameSymbolID(symbol)); if (tmp) symbolFrame = new Symbol(*tmp); } // ... oder ein Headquarter dargestellt werden muss: if ( symbol.getHeadquarter() && !symbolFrame ) { symbolFrame = new Symbol; } // Es musste also wg. a) _fillType oder b) wegen Headquarter ein Symbol erstellt werden: if (symbolFrame) { // symbolFrame mit den relevanten Daten befuellen, damit der key korrekt erstellt werden kann: symbolFrame->setDimen (symbol.getDimen()); symbolFrame->setAffil (symbol.getAffil()); symbolFrame->setHeadquarter(symbol.getHeadquarter()); // reinit l_additionalSymbolData l_additionalSymbolData = SymbolTypes::AdditionalSymbolData(); if(rgbaRole.isValid()) { l_additionalSymbolData.m_filltype =_fillType; } else { l_additionalSymbolData.m_filltype = SymbolTypes::FILLTYPE_OUTLINED; } l_additionalSymbolData.m_state = additionalSymbolData.m_state; l_additionalSymbolData.m_uncertainty = additionalSymbolData.m_uncertainty; const auto key = createKey(*symbolFrame, l_additionalSymbolData, size, rgbaRole, rgbaRole, antiAliased); pmSymbolFrame = _cacheFrames[key]; if (!pmSymbolFrame) { pmSymbolFrame = new QImage(pmSize, ImageFormat); QColor bg = rgbaRole; bg.setAlpha(0); //pmSymbolFrame->setColor(0, bg.rgba()); pmSymbolFrame->fill(bg.rgba()); QPainter painter(pmSymbolFrame); if ( antiAliased ) { painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); } _scene->clear(); SymbolExporter::drawFrameSymbol(*symbolFrame, l_additionalSymbolData, _scene, rgbaLine, rgbaRole, 0.0, antiAliased); SymbolExporter::drawHeadquarterPrims(_scene, symbol.getHeadquarter(), symbol.getDimen(), symbol.getAffil(), rgbaLine); _scene->render(&painter); _cacheFrames.insert(key, pmSymbolFrame); } delete symbolFrame; } ///////////////////////////////////////////////////////////////////////////// // Mobility Symbol ///////////////////////////////////////////////////////////////////////////// QImage *pmSymbolMob = nullptr; if ( (symbol.getMob() != SymbolTypes::MOB_UNDEFINED) && (_mobility != nullptr) ) { const auto symbolMob = _mobility->value(SymbolTable::getMobilitySymbolID(symbol)); if (symbolMob) { const auto key = createKey(*symbolMob, l_additionalSymbolData, size, rgbaLine, rgbaLine, antiAliased); pmSymbolMob = _cacheMobility[key]; if (!pmSymbolMob) { pmSymbolMob = new QImage(pmSize, ImageFormat); QColor bg = rgbaLine; bg.setAlpha(0); //pmSymbolMob->setColor(0, bg.rgba()); pmSymbolMob->fill(bg.rgba()); QPainter painter(pmSymbolMob); if ( antiAliased ) { painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); } _scene->clear(); SymbolExporter::drawSymbol(*symbolMob, symTableCont, _scene, rgbaLine, rgbaLine, 0.0, false, // zwms_roleType outlined: filled prims in role color antiAliased); _scene->render(&painter); _cacheMobility.insert(key, pmSymbolMob); } } } ///////////////////////////////////////////////////////////////////////////// // BCDAB Symbol ///////////////////////////////////////////////////////////////////////////// QImage *pmSymbolBCDAB = nullptr; if ( (symbol.getBcdab() != SymbolTypes::BCDAB_UNDEFINED) && (_bcdab != nullptr) ) { const auto symbolBCDABTmp = _bcdab->value(SymbolTable::getBCDABSymbolID(symbol)); if (symbolBCDABTmp) { Symbol symbolBCDAB(*symbolBCDABTmp); symbolBCDAB.setDimen(symbol.getDimen()); symbolBCDAB.setAffil(symbol.getAffil()); symbolBCDAB.transformSymbol(Symbol::TMG_BCDAB, _branches); const auto key = createKey(symbolBCDAB, l_additionalSymbolData, size, rgbaLine, rgbaLine, antiAliased); pmSymbolBCDAB = _cacheBCDAB[key]; if (!pmSymbolBCDAB) { pmSymbolBCDAB = new QImage(pmSize, ImageFormat); QColor bg = rgbaLine; bg.setAlpha(0); //pmSymbolBCDAB->setColor(0, bg.rgba()); pmSymbolBCDAB->fill(bg.rgba()); QPainter painter(pmSymbolBCDAB); if ( antiAliased ) { painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); } _scene->clear(); SymbolExporter::drawSymbol(symbolBCDAB, symTableCont, _scene, rgbaLine, rgbaLine, 0.0, false, // zwms_roleType outlined: filled prims in role color antiAliased); _scene->render(&painter); _cacheBCDAB.insert(key, pmSymbolBCDAB); } } } ///////////////////////////////////////////////////////////////////////////// // AddOn Symbols ///////////////////////////////////////////////////////////////////////////// QVector pmSymbolAddOn; if ( _addOn != nullptr ) { // vbg : auto idCont = SymbolTable::getVbgSymbolIDs(additionalSymbolData.m_vbg); for (int tmpID : qAsConst(idCont)) { if ( tmpID >= 0 ) { if ( _addOn->contains(tmpID) ) { const Symbol *symbolAddOn = _addOn->value(tmpID); // reinit l_additionalSymbolData l_additionalSymbolData = SymbolTypes::AdditionalSymbolData(); l_additionalSymbolData.m_vbg = additionalSymbolData.m_vbg; const auto key = createKey(*symbolAddOn, l_additionalSymbolData, size, rgbaLine, rgbaLine, antiAliased); const auto cacheAddOnTmp = _cacheAddOn[key]; if (cacheAddOnTmp) { pmSymbolAddOn.append(cacheAddOnTmp); } else { QImage *addOnTmp = new QImage(pmSize, ImageFormat); QColor bg = rgbaLine; bg.setAlpha(0); //addOnTmp->setColor(0, bg.rgba()); addOnTmp->fill(bg.rgba()); QPainter painter(addOnTmp); if ( antiAliased ) { painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); } _scene->clear(); SymbolExporter::drawSymbol(*symbolAddOn, symTableCont, _scene, additionalSymbolData.m_vbg.color, additionalSymbolData.m_vbg.color, 0.0, true, antiAliased); _scene->render(&painter); _cacheAddOn.insert(key, addOnTmp); pmSymbolAddOn.append(addOnTmp); } } } } // modifier_struct : idCont = SymbolTable::getModifierSymbolIDs(additionalSymbolData.m_modifier); for (int tmpID : qAsConst(idCont)) { if ( tmpID >= 0 ) { if ( _addOn->contains(tmpID) ) { const Symbol *symbolAddOn = _addOn->value(tmpID); // reinit l_additionalSymbolData l_additionalSymbolData = SymbolTypes::AdditionalSymbolData(); l_additionalSymbolData.m_modifier = additionalSymbolData.m_modifier; const auto key = createKey(*symbolAddOn, l_additionalSymbolData, size, rgbaLine, rgbaLine, antiAliased); const auto addOnTmp = _cacheAddOn[key]; if (addOnTmp) { pmSymbolAddOn.append(addOnTmp); } else { QImage *addOnTmp2 = new QImage(pmSize, ImageFormat); QColor bg = rgbaLine; bg.setAlpha(0); //addOnTmp->setColor(0, bg.rgba()); addOnTmp2->fill(bg.rgba()); QPainter painter(addOnTmp2); if ( antiAliased ) { painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); } _scene->clear(); SymbolExporter::drawSymbol(*symbolAddOn, symTableCont, _scene, rgbaRole, rgbaRole, 0.0, true, antiAliased); _scene->render(&painter); _cacheAddOn.insert(key, addOnTmp2); pmSymbolAddOn.append(addOnTmp2); } } } } // for } ///////////////////////////////////////////////////////////////////////////// // Full rendered Symbol ///////////////////////////////////////////////////////////////////////////// int offsetX = (pmSize.width() - size.width()) / 2; int offsetY = (pmSize.height() - size.height()) / 2; QImage pmSymbolFull(pmSize, ImageFormat); QColor bg = rgbaLine; bg.setAlpha(0); //pmSymbolFull.setColor(0, bg.rgba()); pmSymbolFull.fill(bg.rgba()); QPainter painter(&pmSymbolFull); if ( antiAliased ) { painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform); } //////////////////////////////////////////// // Rotation (used for Heading of symbols) //////////////////////////////////////////// qreal cx = pmSize.width() / 2.0; qreal cy = pmSize.height() / 2.0; int rotAngle = additionalSymbolData.m_rotationAngle; painter.setTransform( QTransform().translate(cy, cy).rotate(rotAngle).translate(-cx, -cy) ); //////////////////////////////////////////// if ( pmSymbolFrame != nullptr ) { QRect r = pmSymbolFrame->rect(); // r.moveTo(offsetX, offsetY); painter.drawImage(r, *pmSymbolFrame, pmSymbolFrame->rect()); } if ( pmSymbolVehicle != nullptr ) { QRect r = pmSymbolVehicle->rect(); r.moveTo(offsetX, offsetY); painter.drawImage(r, *pmSymbolVehicle, pmSymbolVehicle->rect()); } if ( pmSymbolIntrinsicMob != nullptr ) { QRect r = pmSymbolIntrinsicMob->rect(); r.moveTo(offsetX, offsetY); painter.drawImage(r, *pmSymbolIntrinsicMob, pmSymbolIntrinsicMob->rect()); } if ( pmSymbolArming != nullptr ) { QRect r = pmSymbolArming->rect(); r.moveTo(offsetX, offsetY); painter.drawImage(r, *pmSymbolArming, pmSymbolArming->rect()); } if ( pmSymbolSectorIcon != nullptr ) { QRect r = pmSymbolSectorIcon->rect(); r.moveTo(offsetX, offsetY); painter.drawImage(r, *pmSymbolSectorIcon, pmSymbolSectorIcon->rect()); } for (int i=0; irect(); r.moveTo(offsetX, offsetY); painter.drawImage(r, *(pmSymbolMisc.at(i)), pmSymbolMisc.at(i)->rect()); } if ( pmSymbolCL != nullptr ) { QRect r = pmSymbolCL->rect(); r.moveTo(offsetX, offsetY); painter.drawImage(r, *pmSymbolCL, pmSymbolCL->rect()); } for (int i=0; irect(); r.moveTo(offsetX, offsetY); painter.drawImage(r, *(pmSymbolBT.at(i)), pmSymbolBT.at(i)->rect()); } // The big ones do not need an Offset if ( pmSymbolMob != nullptr ) { painter.drawImage(pmSymbolMob->rect(), *pmSymbolMob, pmSymbolMob->rect()); } if ( pmSymbolBCDAB != nullptr ) { painter.drawImage(pmSymbolBCDAB->rect(), *pmSymbolBCDAB, pmSymbolBCDAB->rect()); } if ( pmSymbolMain != nullptr ) { QRect r = pmSymbolMain->rect(); r.moveTo(offsetX, offsetY); painter.drawImage(r, *pmSymbolMain, pmSymbolMain->rect()); } // AddOn Symbols: for (const QImage *img : qAsConst(pmSymbolAddOn)) { QRect r = img->rect(); painter.drawImage(r, *img, r); } QTransform transformView; transformView.scale(1.0, -1.0); // transformView.rotate( 360 ); // rotation here leads to bad looking symbols QImage pmSymbolFullTransformed(pmSymbolFull.transformed(transformView)); if (updateCache) { const auto key = createKey(symbol, additionalSymbolData, size, rgbaLine, rgbaRole, antiAliased); _cacheFullSymbols.insert(key, new QImage(pmSymbolFullTransformed)); } return pmSymbolFullTransformed; } // QImage PixmapSymbolCache::createPixmap(const Symbol& symbol... PixmapSymbolCache::PixmapSymbolCache() : _cacheFullSymbols(1000), _cacheMainSymbols(1000), _cacheFrames(500), _cacheMobility(500), _cacheBCDAB(500), _cacheCommandLevel(500), _cacheBranches(500), _cacheVehicle(50), _cacheIntrinsicMobility(50), _cacheArming(50), _cacheMisc(500), _cacheAddOn(10), _cacheSectorIcon(100), _scene(new QGraphicsScene()), _id(-1) { } // PixmapSymbolCache::PixmapSymbolCache() PixmapSymbolCache::~PixmapSymbolCache() { delete _scene; delete _frames; delete _mobility; delete _bcdab; delete _commandLevel; delete _branches; delete _vehicle; delete _intrinsicMobility; delete _arming; delete _misc; delete _addOn; delete _sectorIcon; } // PixmapSymbolCache::~PixmapSymbolCache() void PixmapSymbolCache::moveToThread(QThread *t) { _scene->moveToThread(t); } void PixmapSymbolCache::setId(int id) { _id = id; } int PixmapSymbolCache::id() const { return _id; } } // namespace SymbologyXML