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