File indexing completed on 2025-01-05 03:59:19

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <tackat@kde.org>
0004 // SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org>
0005 //
0006 
0007 #include <QApplication>
0008 #include <QPainter>
0009 #include <QPainterPath>
0010 #include <QPalette>
0011 #include <QPixmapCache>
0012 
0013 #include "VisiblePlacemark.h"
0014 #include "RemoteIconLoader.h"
0015 #include "GeoDataPlacemark.h"
0016 #include "GeoDataStyle.h"
0017 #include "GeoDataIconStyle.h"
0018 #include "GeoDataLabelStyle.h"
0019 #include "PlacemarkLayer.h"
0020 
0021 #include "digikam_debug.h"
0022 
0023 using namespace Marble;
0024 
0025 VisiblePlacemark::VisiblePlacemark( const GeoDataPlacemark *placemark, const GeoDataCoordinates &coordinates, const GeoDataStyle::ConstPtr &style )
0026     : m_placemark( placemark ),
0027       m_selected( false ),
0028       m_labelDirty(true),
0029       m_style(style),
0030       m_coordinates(coordinates)
0031 {
0032     const RemoteIconLoader *remoteLoader = style->iconStyle().remoteIconLoader();
0033     QObject::connect( remoteLoader, SIGNAL(iconReady()),
0034                      this, SLOT(setSymbolPixmap()) );
0035 
0036     setSymbolPixmap();
0037 }
0038 
0039 const GeoDataPlacemark* VisiblePlacemark::placemark() const
0040 {
0041     return m_placemark;
0042 }
0043 
0044 const QPixmap& VisiblePlacemark::symbolPixmap() const
0045 {
0046     if (!m_symbolId.isEmpty() && m_symbolPixmap.isNull()) {
0047         if ( !QPixmapCache::find( m_symbolId, &m_symbolPixmap ) ) {
0048             m_symbolPixmap = QPixmap::fromImage(m_style->iconStyle().scaledIcon());
0049             QPixmapCache::insert( m_symbolId, m_symbolPixmap);
0050         }
0051     }
0052     return m_symbolPixmap;
0053 }
0054 
0055 const QString& VisiblePlacemark::symbolId() const
0056 {
0057     return m_symbolId;
0058 }
0059 
0060 bool VisiblePlacemark::selected() const
0061 {
0062     return m_selected;
0063 }
0064 
0065 void VisiblePlacemark::setSelected( bool selected )
0066 {
0067     if (selected != m_selected) {
0068         m_selected = selected;
0069         m_labelDirty = true;
0070     }
0071 }
0072 
0073 const QPointF& VisiblePlacemark::symbolPosition() const
0074 {
0075     return m_symbolPosition;
0076 }
0077 
0078 const QPointF VisiblePlacemark::hotSpot() const
0079 {
0080     const QSize iconSize = m_style->iconStyle().scaledIcon().size();
0081 
0082     GeoDataHotSpot::Units xunits;
0083     GeoDataHotSpot::Units yunits;
0084     QPointF pixelHotSpot = m_style->iconStyle().hotSpot( xunits, yunits );
0085 
0086     switch ( xunits ) {
0087     case GeoDataHotSpot::Fraction:
0088         pixelHotSpot.setX( iconSize.width() * pixelHotSpot.x() );
0089         break;
0090     case GeoDataHotSpot::Pixels:
0091         /* nothing to do */
0092         break;
0093     case GeoDataHotSpot::InsetPixels:
0094         pixelHotSpot.setX( iconSize.width() - pixelHotSpot.x() );
0095         break;
0096     }
0097 
0098     switch ( yunits ) {
0099     case GeoDataHotSpot::Fraction:
0100         pixelHotSpot.setY( iconSize.height() * ( 1.0 - pixelHotSpot.y() ) );
0101         break;
0102     case GeoDataHotSpot::Pixels:
0103         /* nothing to do */
0104         break;
0105     case GeoDataHotSpot::InsetPixels:
0106         pixelHotSpot.setY( iconSize.height() - pixelHotSpot.y() );
0107         break;
0108     }
0109 
0110     return pixelHotSpot;
0111 }
0112 
0113 void VisiblePlacemark::setSymbolPosition( const QPointF& position )
0114 {
0115     m_symbolPosition = position;
0116 }
0117 
0118 const QPixmap& VisiblePlacemark::labelPixmap()
0119 {
0120     if (m_labelDirty) {
0121         drawLabelPixmap();
0122     }
0123 
0124     return m_labelPixmap;
0125 }
0126 
0127 void VisiblePlacemark::setSymbolPixmap()
0128 {
0129     if (m_style) {
0130         m_symbolId = m_style->iconStyle().iconPath() + QString::number(m_style->iconStyle().scale());
0131         if (m_style->iconStyle().iconPath().isEmpty()) {
0132             m_symbolId.clear();
0133             m_symbolPixmap = QPixmap::fromImage(m_style->iconStyle().scaledIcon());
0134         }
0135         Q_EMIT updateNeeded();
0136     }
0137     else {
0138         qCDebug(DIGIKAM_MARBLE_LOG) << "Style pointer is Null";
0139     }
0140 }
0141 
0142 const QRectF& VisiblePlacemark::labelRect() const
0143 {
0144     return m_labelRect;
0145 }
0146 
0147 void VisiblePlacemark::setLabelRect( const QRectF& labelRect )
0148 {
0149     m_labelRect = labelRect;
0150 }
0151 
0152 void VisiblePlacemark::setStyle(const GeoDataStyle::ConstPtr &style)
0153 {
0154     m_style = style;
0155     m_labelDirty = true;
0156     setSymbolPixmap();
0157 }
0158 
0159 GeoDataStyle::ConstPtr VisiblePlacemark::style() const
0160 {
0161     return m_style;
0162 }
0163 
0164 QRectF VisiblePlacemark::symbolRect() const
0165 {
0166     return QRectF(m_symbolPosition, m_symbolPixmap.size());
0167 }
0168 
0169 QRectF VisiblePlacemark::boundingBox() const
0170 {
0171     return m_labelRect.isEmpty() ? symbolRect() : m_labelRect.united(symbolRect());
0172 }
0173 
0174 const GeoDataCoordinates &VisiblePlacemark::coordinates() const
0175 {
0176     return m_coordinates;
0177 }
0178 
0179 void VisiblePlacemark::drawLabelPixmap()
0180 {
0181     m_labelDirty = false;
0182     QString labelName = m_placemark->displayName();
0183     if ( labelName.isEmpty() || m_style->labelStyle().color() == QColor(Qt::transparent) ) {
0184         m_labelPixmap = QPixmap();
0185         return;
0186     }
0187 
0188     QFont  labelFont  = m_style->labelStyle().scaledFont();
0189     QColor labelColor = m_style->labelStyle().color();
0190 
0191     LabelStyle labelStyle = Normal;
0192     if ( m_selected ) {
0193         labelStyle = Selected;
0194     } else if ( m_style->labelStyle().glow() ) {
0195         labelStyle = Glow;
0196     }
0197 
0198     int textHeight = QFontMetrics( labelFont ).height();
0199 
0200     int textWidth;
0201     if ( m_style->labelStyle().glow() ) {
0202         labelFont.setWeight( QFont::Bold ); // Needed to calculate the correct pixmap size;
0203         textWidth = ( QFontMetrics( labelFont ).horizontalAdvance( labelName )
0204             + qRound( 2 * s_labelOutlineWidth ) );
0205     } else {
0206         textWidth = ( QFontMetrics( labelFont ).horizontalAdvance( labelName ) );
0207     }
0208 
0209     m_labelPixmap = QPixmap( QSize( textWidth, textHeight ) );
0210     m_labelPixmap.fill( Qt::transparent );
0211 
0212     QPainter labelPainter( &m_labelPixmap );
0213 
0214     drawLabelText( labelPainter, labelName, labelFont, labelStyle, labelColor );
0215 }
0216 
0217 void VisiblePlacemark::drawLabelText(QPainter &labelPainter, const QString &text,
0218                                             const QFont &labelFont, LabelStyle labelStyle, const QColor &color )
0219 {
0220     QFont font = labelFont;
0221     QFontMetrics metrics = QFontMetrics( font );
0222     int fontAscent = metrics.ascent();
0223 
0224     switch ( labelStyle ) {
0225     case Selected: {
0226         labelPainter.setPen( color );
0227         labelPainter.setFont( font );
0228         QRect textRect( 0, 0, metrics.horizontalAdvance( text ), metrics.height() );
0229         labelPainter.fillRect( textRect, QApplication::palette().highlight() );
0230         labelPainter.setPen( QPen( QApplication::palette().highlightedText(), 1 ) );
0231         labelPainter.drawText( 0, fontAscent, text );
0232         break;
0233     }
0234     case Glow: {
0235         font.setWeight( QFont::Bold );
0236         fontAscent = QFontMetrics( font ).ascent();
0237 
0238         QPen outlinepen( (color.red() + color.green() + color.blue())/3 < 160 ? Qt::white : Qt::black);
0239         outlinepen.setWidthF( s_labelOutlineWidth );
0240         QBrush  outlinebrush( color );
0241 
0242         QPainterPath outlinepath;
0243 
0244         const QPointF  baseline( s_labelOutlineWidth / 2.0, fontAscent );
0245         outlinepath.addText( baseline, font, text );
0246         labelPainter.setRenderHint( QPainter::Antialiasing, true );
0247         labelPainter.setPen( outlinepen );
0248         labelPainter.setBrush( outlinebrush );
0249         labelPainter.drawPath( outlinepath );
0250         labelPainter.setPen( Qt::NoPen );
0251         labelPainter.drawPath( outlinepath );
0252         labelPainter.setRenderHint( QPainter::Antialiasing, false );
0253         break;
0254     }
0255     default: {
0256         labelPainter.setPen( color );
0257         labelPainter.setFont( font );
0258         labelPainter.drawText( 0, fontAscent, text );
0259     }
0260     }
0261 }
0262 
0263 #include "moc_VisiblePlacemark.cpp"