Marble

VisiblePlacemark.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <[email protected]>
4 // SPDX-FileCopyrightText: 2007 Inge Wallin <[email protected]>
5 //
6 
7 #include "VisiblePlacemark.h"
8 
9 #include "MarbleDebug.h"
10 #include "RemoteIconLoader.h"
11 
12 #include "GeoDataPlacemark.h"
13 #include "GeoDataStyle.h"
14 #include "GeoDataIconStyle.h"
15 #include "GeoDataLabelStyle.h"
16 #include "PlacemarkLayer.h"
17 
18 #include <QApplication>
19 #include <QPainter>
20 #include <QPainterPath>
21 #include <QPalette>
22 #include <QPixmapCache>
23 
24 using namespace Marble;
25 
26 VisiblePlacemark::VisiblePlacemark( const GeoDataPlacemark *placemark, const GeoDataCoordinates &coordinates, const GeoDataStyle::ConstPtr &style )
27  : m_placemark( placemark ),
28  m_selected( false ),
29  m_labelDirty(true),
30  m_style(style),
31  m_coordinates(coordinates)
32 {
33  const RemoteIconLoader *remoteLoader = style->iconStyle().remoteIconLoader();
34  QObject::connect( remoteLoader, SIGNAL(iconReady()),
35  this, SLOT(setSymbolPixmap()) );
36 
37  setSymbolPixmap();
38 }
39 
41 {
42  return m_placemark;
43 }
44 
46 {
47  if (!m_symbolId.isEmpty() && m_symbolPixmap.isNull()) {
48  if ( !QPixmapCache::find( m_symbolId, &m_symbolPixmap ) ) {
49  m_symbolPixmap = QPixmap::fromImage(m_style->iconStyle().scaledIcon());
50  QPixmapCache::insert( m_symbolId, m_symbolPixmap);
51  }
52  }
53  return m_symbolPixmap;
54 }
55 
57 {
58  return m_symbolId;
59 }
60 
62 {
63  return m_selected;
64 }
65 
66 void VisiblePlacemark::setSelected( bool selected )
67 {
68  if (selected != m_selected) {
69  m_selected = selected;
70  m_labelDirty = true;
71  }
72 }
73 
75 {
76  return m_symbolPosition;
77 }
78 
80 {
81  const QSize iconSize = m_style->iconStyle().scaledIcon().size();
82 
83  GeoDataHotSpot::Units xunits;
84  GeoDataHotSpot::Units yunits;
85  QPointF pixelHotSpot = m_style->iconStyle().hotSpot( xunits, yunits );
86 
87  switch ( xunits ) {
88  case GeoDataHotSpot::Fraction:
89  pixelHotSpot.setX( iconSize.width() * pixelHotSpot.x() );
90  break;
91  case GeoDataHotSpot::Pixels:
92  /* nothing to do */
93  break;
94  case GeoDataHotSpot::InsetPixels:
95  pixelHotSpot.setX( iconSize.width() - pixelHotSpot.x() );
96  break;
97  }
98 
99  switch ( yunits ) {
100  case GeoDataHotSpot::Fraction:
101  pixelHotSpot.setY( iconSize.height() * ( 1.0 - pixelHotSpot.y() ) );
102  break;
103  case GeoDataHotSpot::Pixels:
104  /* nothing to do */
105  break;
106  case GeoDataHotSpot::InsetPixels:
107  pixelHotSpot.setY( iconSize.height() - pixelHotSpot.y() );
108  break;
109  }
110 
111  return pixelHotSpot;
112 }
113 
115 {
116  m_symbolPosition = position;
117 }
118 
120 {
121  if (m_labelDirty) {
122  drawLabelPixmap();
123  }
124 
125  return m_labelPixmap;
126 }
127 
128 void VisiblePlacemark::setSymbolPixmap()
129 {
130  if (m_style) {
131  m_symbolId = m_style->iconStyle().iconPath() + QString::number(m_style->iconStyle().scale());
132  if (m_style->iconStyle().iconPath().isEmpty()) {
133  m_symbolId.clear();
134  m_symbolPixmap = QPixmap::fromImage(m_style->iconStyle().scaledIcon());
135  }
136  emit updateNeeded();
137  }
138  else {
139  mDebug() << "Style pointer is Null";
140  }
141 }
142 
144 {
145  return m_labelRect;
146 }
147 
148 void VisiblePlacemark::setLabelRect( const QRectF& labelRect )
149 {
150  m_labelRect = labelRect;
151 }
152 
153 void VisiblePlacemark::setStyle(const GeoDataStyle::ConstPtr &style)
154 {
155  m_style = style;
156  m_labelDirty = true;
157  setSymbolPixmap();
158 }
159 
160 GeoDataStyle::ConstPtr VisiblePlacemark::style() const
161 {
162  return m_style;
163 }
164 
165 QRectF VisiblePlacemark::symbolRect() const
166 {
167  return QRectF(m_symbolPosition, m_symbolPixmap.size());
168 }
169 
170 QRectF VisiblePlacemark::boundingBox() const
171 {
172  return m_labelRect.isEmpty() ? symbolRect() : m_labelRect.united(symbolRect());
173 }
174 
175 const GeoDataCoordinates &VisiblePlacemark::coordinates() const
176 {
177  return m_coordinates;
178 }
179 
180 void VisiblePlacemark::drawLabelPixmap()
181 {
182  m_labelDirty = false;
183  QString labelName = m_placemark->displayName();
184  if ( labelName.isEmpty() || m_style->labelStyle().color() == QColor(Qt::transparent) ) {
185  m_labelPixmap = QPixmap();
186  return;
187  }
188 
189  QFont labelFont = m_style->labelStyle().scaledFont();
190  QColor labelColor = m_style->labelStyle().color();
191 
192  LabelStyle labelStyle = Normal;
193  if ( m_selected ) {
194  labelStyle = Selected;
195  } else if ( m_style->labelStyle().glow() ) {
196  labelStyle = Glow;
197  }
198 
199  int textHeight = QFontMetrics( labelFont ).height();
200 
201  int textWidth;
202  if ( m_style->labelStyle().glow() ) {
203  labelFont.setWeight( 75 ); // Needed to calculate the correct pixmap size;
204  textWidth = ( QFontMetrics( labelFont ).horizontalAdvance( labelName )
205  + qRound( 2 * s_labelOutlineWidth ) );
206  } else {
207  textWidth = ( QFontMetrics( labelFont ).horizontalAdvance( labelName ) );
208  }
209 
210  m_labelPixmap = QPixmap( QSize( textWidth, textHeight ) );
211  m_labelPixmap.fill( Qt::transparent );
212 
213  QPainter labelPainter( &m_labelPixmap );
214 
215  drawLabelText( labelPainter, labelName, labelFont, labelStyle, labelColor );
216 }
217 
218 void VisiblePlacemark::drawLabelText(QPainter &labelPainter, const QString &text,
219  const QFont &labelFont, LabelStyle labelStyle, const QColor &color )
220 {
221  QFont font = labelFont;
222  QFontMetrics metrics = QFontMetrics( font );
223  int fontAscent = metrics.ascent();
224 
225  switch ( labelStyle ) {
226  case Selected: {
227  labelPainter.setPen( color );
228  labelPainter.setFont( font );
229  QRect textRect( 0, 0, metrics.horizontalAdvance( text ), metrics.height() );
230  labelPainter.fillRect( textRect, QApplication::palette().highlight() );
231  labelPainter.setPen( QPen( QApplication::palette().highlightedText(), 1 ) );
232  labelPainter.drawText( 0, fontAscent, text );
233  break;
234  }
235  case Glow: {
236  font.setWeight( 75 );
237  fontAscent = QFontMetrics( font ).ascent();
238 
239  QPen outlinepen( (color.red() + color.green() + color.blue())/3 < 160 ? Qt::white : Qt::black);
240  outlinepen.setWidthF( s_labelOutlineWidth );
241  QBrush outlinebrush( color );
242 
243  QPainterPath outlinepath;
244 
245  const QPointF baseline( s_labelOutlineWidth / 2.0, fontAscent );
246  outlinepath.addText( baseline, font, text );
247  labelPainter.setRenderHint( QPainter::Antialiasing, true );
248  labelPainter.setPen( outlinepen );
249  labelPainter.setBrush( outlinebrush );
250  labelPainter.drawPath( outlinepath );
251  labelPainter.setPen( Qt::NoPen );
252  labelPainter.drawPath( outlinepath );
253  labelPainter.setRenderHint( QPainter::Antialiasing, false );
254  break;
255  }
256  default: {
257  labelPainter.setPen( color );
258  labelPainter.setFont( font );
259  labelPainter.drawText( 0, fontAscent, text );
260  }
261  }
262 }
263 
264 #include "moc_VisiblePlacemark.cpp"
A 3d point representation.
const QPixmap & symbolPixmap() const
Returns the pixmap of the place mark symbol.
void setLabelRect(const QRectF &area)
Sets the area covered by the place mark name label on the map.
void setPen(const QColor &color)
QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags)
QString number(int n, int base)
void setSelected(bool selected)
Sets the state of the place mark.
QSize size() const const
const QPixmap & labelPixmap()
Returns the pixmap of the place mark name label.
const QRectF & labelRect() const
Returns the area covered by the place mark name label on the map.
void clear()
int horizontalAdvance(const QString &text, int len) const const
void addText(const QPointF &point, const QFont &font, const QString &text)
int red() const const
void fill(const QColor &color)
int ascent() const const
bool selected() const
Returns the state of the place mark.
int width() const const
void drawText(const QPointF &position, const QString &text)
void fillRect(const QRectF &rectangle, const QBrush &brush)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void setX(qreal x)
void setY(qreal y)
int height() const const
const GeoDataPlacemark * placemark() const
Returns the index of the place mark model which is associated with this visible place mark.
bool isEmpty() const const
void drawPath(const QPainterPath &path)
int green() const const
Binds a QML item to a specific geodetic location in screen coordinates.
bool isEmpty() const const
void setBrush(const QBrush &brush)
a class representing a point of interest on the map
const QString & symbolId() const
Returns the id for the place mark symbol.
bool isNull() const const
QPixmap * find(const QString &key)
const QPointF & symbolPosition() const
Returns the position of the place mark symbol on the map.
void setSymbolPosition(const QPointF &position)
Sets the position of the place mark symbol on the map.
qreal x() const const
qreal y() const const
const QPointF hotSpot() const
Returns the top left corner of the place mark symbol's hot spot.
int blue() const const
void setWeight(int weight)
QString displayName() const
displays the name of a place in the locale language of the user
QPalette palette()
void setRenderHint(QPainter::RenderHint hint, bool on)
void setFont(const QFont &font)
bool insert(const QString &key, const QPixmap &pixmap)
int height() const const
transparent
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:31
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Sep 27 2023 04:09:08 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.