/** * @RDE_HEADER@ * Class ExtensionRenderer * $Id$ * $HeadURL$ * $Author$ */ // Own #include "symbol_extension_renderer.h" #include "sidc_codec.h" // ESRI // Qt #include #include const double g_factor = 0.95; namespace AdvancedSymbology { QImage ExtensionRenderer::createFullImage(int sizeL, const QColor &fillColor) { const int fullSizeW = sizeL * 1.7; // FRIEND 1.5 L const int fullSizeH = sizeL * 1.7; // try and error: '1.7'; // N. Thoden, 17.03.2020: // Increase height to 2.2 to avoid FeintDummy (and mobility?) exceeds upper edge. // But unfortunately then the map_object_custom_view has small icons - :-( // Stay at 1.7 QImage fullImage(fullSizeW, fullSizeH, QImage::Format_ARGB32); if (fillColor.isValid()) fullImage.fill(fillColor); else fullImage.fill(Qt::transparent); // for debugging : if (0) { QPainter painter(&fullImage); QPen pen(Qt::black); pen.setWidth(2.0); painter.setPen(pen); painter.drawRect(fullImage.rect()); } // : for debugging return fullImage; } void ExtensionRenderer::renderMarking(QImage &fullImage, const QColor &color) { QPainter painter(&fullImage); painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); QRect smallerRect(0, 0, fullImage.width()*g_factor, fullImage.width()*g_factor); // we know, that the fullImage has more height, than width const QPoint offset(((fullImage.width() - smallerRect.width()) / 2), ((fullImage.height() - smallerRect.height()) / 2)); smallerRect.moveTo(offset); painter.setPen(QPen(Qt::NoPen)); // rect with no outter line // maybe: QColor colorWithoutAlpha = color; colorWithoutAlpha.setAlpha(255); painter.setBrush(QBrush(color, Qt::Dense5Pattern)); // fillPattern (Dense4Pattern .. Dense6Pattern) painter.drawRect(smallerRect); painter.end(); } // hotSpotOfCoreImage - not be finished QPoint hotSpotOfCoreImage(const QImage &coreImage, const QString &sidc) { int hqFdTf = QString(sidc[7]).toInt(); if ((hqFdTf < 1) || ((hqFdTf > 7))) return QPoint(); // int identity = QString(sidc[3]).toInt(); // bool taskForce = hqFdTf & 4; // mask // bool headquarters = hqFdTf & 2; // mask // bool feintDummy = hqFdTf & 1; // mask /* *Identity Pending, ///< 0 Unknown, ///< 1 AssumedFriend, ///< 2 Friend, ///< 3 Neutral, ///< 4 SuspectJoker, ///< 5 HostileFaker ///< 6 */ // set x value: QPoint hotSpot = coreImage.rect().center(); // set y value: // do not honor the frame (unknown/hostile vs. friend/neutral) // accept a small error to ease the calculation: // move hotSpot to bottom -> / // move hotSpot to top -> * switch (hqFdTf) { case 1: case 5: hotSpot.ry() *= 1.3; break; case 2: hotSpot.ry() /= 1.7; break; case 3: case 4: // empty (it´s not worth) break; case 6: case 7: case 8: break; } // switch return hotSpot; } QVector ExtensionRenderer::identityToColor(const QString &sidc) { // The following color constants are taken from ArcGis Qt-SDK 10.2.5 const QString &rawSidc = SidcCodec::decodeRawSidc(sidc); QVector colorVec; colorVec.reserve(2); if (rawSidc.length() >= 4) { const QChar pos2 = rawSidc[1]; // according Mil2525Charlie const QChar ident = rawSidc[3]; // according Mil2525Delta // Unknown if (ident == QLatin1Char('0') || ident == QLatin1Char('1') || pos2 == QLatin1Char('U') || pos2 == QLatin1Char('P') || pos2 == QLatin1Char('G') || pos2 == QLatin1Char('W') ) { colorVec.append(QColor(255, 255, 128)); colorVec.append(QColor(255, 255, 0)); // 10012500002108000000@Mil2525D: color = QColor(255, 255, 0); // secondary: colorVec.append(QColor(239, 239, 15)); // SchadMat: 10012500003210000000@MilAPP6D: color = QColor(239, 239, 15) = some kind of yellow } // Friend else if (ident == QLatin1Char('2') || ident == QLatin1Char('3') || pos2 == QLatin1Char('F') || pos2 == QLatin1Char('A') || pos2 == QLatin1Char('M') || pos2 == QLatin1Char('D') ) { colorVec.append(QColor(128, 224, 255)); // secondary: colorVec.append(QColor(0, 0, 0)); // SchadMat: 10032500003210000000@MilAPP6D: color = QColor(0, 0, 0) = black } // Neutral else if (ident == QLatin1Char('4') || pos2 == QLatin1Char('N') || pos2 == QLatin1Char('L') ) { colorVec.append(QColor(170, 255, 170)); // secondary: colorVec.append(QColor(0, 255, 0)); // SchadMat: 10042500003210000000@MilAPP6D: color = QColor(0, 0, 0) = some kind of light green colorVec.append(QColor(85, 255, 0)); // MedVaclandezone?: 10042500003211000000@MilAPP6D: color = QColor(0, 0, 0) = some kind of light green } // Hostile else if (ident == QLatin1Char('5') || ident == QLatin1Char('6') || pos2 == QLatin1Char('H') || pos2 == QLatin1Char('S') ) { colorVec.append(QColor(255, 128, 128)); // secondary: colorVec.append(QColor(255, 0, 0)); // SchadMat: 10062500003210000000@MilAPP6D: color = QColor(255, 0, 0) = red } } // if (rawSidc.length() >= 2) return colorVec; } bool ExtensionRenderer::replaceColor(QImage &img, const QRgb &oldColor, const QRgb &newColor) { #ifdef REPLACE_COLOR_DEBUG std::cerr << " oldColor=" << oldColor << " newColor=" << newColor << std::endl; #endif // REPLACE_COLOR_DEBUG bool modified = false; if (img.format() != QImage::Format_RGB32 && img.format() != QImage::Format_ARGB32) { img = img.convertToFormat(QImage::Format_ARGB32); modified = true; } if (oldColor != newColor) { int xmax = img.width(); int ymax = img.height(); for (int x = 0; x < xmax; ++x) { for (int y = 0; y < ymax; ++y) { const QPoint curPixel(x, y); const QRgb &pixel = img.pixel(curPixel); if (pixel == oldColor) { img.setPixel(curPixel, newColor); modified = true; } } // for } // for } return modified; } void ExtensionRenderer::mergeCoreImageIntoFullImage(QImage &fullImage, const QImage &coreImage) { QPainter painter(&fullImage); painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); QPoint offset((fullImage.width() - coreImage.width()) / 2, (fullImage.height() - coreImage.height()) / 2); QRect r = coreImage.rect(); r.moveTo(offset); painter.drawImage(r, coreImage, coreImage.rect()); painter.end(); } void ExtensionRenderer::renderInjuryAddSymbols(QImage &fullImage, const Injury &injury, const QColor &injuryColor, const AdditionalSymbolTypeCont &additionalSymbols, const QColor &mainColor) { QPainter painter(&fullImage); painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); int width = fullImage.size().width(); // scaled and centered rect; QRect smallerRect(0, 0, fullImage.width()*g_factor, fullImage.width()*g_factor); // we know, that the fullImage has more height, than width const QPoint offset(((fullImage.width() - smallerRect.width()) / 2), ((fullImage.height() - smallerRect.height()) / 2)); smallerRect.moveTo(offset); // // handle additionalSymbolType // { int penWidth = width / 25; for (AdditionalSymbolType additionalSymbolType : additionalSymbols) { double dimensionX = smallerRect.size().width(); // small double dimensionY = fullImage.size().height(); // big // // First switch // QColor col = Qt::red; switch (additionalSymbolType) { case AdditionalSymbolType::Manipulation: col = Qt::black; dimensionY -= penWidth * 2.5; break; case AdditionalSymbolType::NoPosition: col = Qt::red; dimensionY -= penWidth * 1.5; break; case AdditionalSymbolType::BiteError: col = Qt::yellow; dimensionY -= penWidth * 0.5; break; case AdditionalSymbolType::NbcProtection: col = mainColor; break; } //switch (additionalSymbolType) // // Second switch // switch (additionalSymbolType) { case AdditionalSymbolType::Manipulation: { QPen pen(col); pen.setWidth(penWidth); double stepWidth = dimensionX / 6.0; for (int i = 0; i < 6; ++i) { if (i % 2) pen.setColor(Qt::white); else pen.setColor(col); painter.setPen(pen); painter.drawLine(QPointF(smallerRect.left() + stepWidth * i, dimensionY), QPointF(smallerRect.left() + stepWidth * (i + 1), dimensionY)); } } break; case AdditionalSymbolType::BiteError: case AdditionalSymbolType::NoPosition: { QPen pen(col); pen.setWidth(penWidth); painter.setPen(pen); painter.drawLine(QPointF(smallerRect.left(), dimensionY), QPointF(smallerRect.right(), dimensionY)); } break; case AdditionalSymbolType::NbcProtection: { int y = (penWidth / 2.0) + (width * 0.01); QPen pen(col); pen.setWidth(penWidth); painter.setPen(pen); painter.drawLine(QPointF(smallerRect.left(), y), QPointF(smallerRect.center().x() - (width * 0.1), y)); } } // switch } // for } // additionalSymbolType // // handle injury // { int penWidth = width / 20; QPen pen(injuryColor); pen.setWidth(penWidth); painter.setPen(pen); // handle injury {Hit, MobilityKill, WeaponKill, TotalKill} switch (injury) { case AdvancedSymbology::Injury::Hit: { QPoint left(smallerRect.left(), fullImage.height() / 2); QPoint right(smallerRect.right(), fullImage.height() / 2); painter.drawLine(left, right); } break; case AdvancedSymbology::Injury::MobilityKill: painter.drawLine(smallerRect.topLeft(), smallerRect.bottomRight()); break; case AdvancedSymbology::Injury::WeaponKill: painter.drawLine(smallerRect.bottomLeft(), smallerRect.topRight()); break; case AdvancedSymbology::Injury::TotalKill: painter.drawLine(smallerRect.topLeft(), smallerRect.bottomRight()); painter.drawLine(smallerRect.bottomLeft(), smallerRect.topRight()); break; case AdvancedSymbology::Injury::NoInjury: break; } // switch } // injury painter.end(); } } // namespace AdvancedSymbology