Files
qt5-legatus-legacy/Lts/Viewer/SituationMap/SymbologyXML/pixmap_symbol_cache.cpp
T
2026-08-13 18:33:10 +02:00

1218 lines
41 KiB
C++
Executable File

/**
* @RDE_HEADER@
* $Id$
* $HeadURL$
* $Author$
*/
#include "pixmap_symbol_cache.h"
#include "symbol_exporter.h"
#include "symbol_table.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <QCoreApplication>
#include <QPainter>
#include <QGraphicsScene>
#include <QMap>
namespace SymbologyXML
{
static const QImage::Format ImageFormat = QImage::Format_ARGB32;
//-----------------------------------------------------------------------------
QSharedPointer<PixmapSymbolCache> PixmapSymbolCache::instance()
{
static QWeakPointer<PixmapSymbolCache> 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 <QByteArray, QImage> *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<QImage *> 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<QImage *> pmSymbolBT;
if ( _branches != nullptr )
{
for (unsigned int i=0; i<symbol._branchTags.size(); ++i)
{
if ( symbol._branchTags.at(i) )
{
const Symbol *symbolBTTmp = _branches->value(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<QImage *> 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; i<pmSymbolMisc.size(); ++i)
{
QRect r = pmSymbolMisc.at(i)->rect();
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; i<pmSymbolBT.size(); ++i)
{
QRect r = pmSymbolBT.at(i)->rect();
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