Kstars

skylabeler.cpp
1/*
2 SPDX-FileCopyrightText: 2007 James B. Bowlin <bowlin@mindspring.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "skylabeler.h"
8
9#include <cstdio>
10
11#include <QPainter>
12#include <QPixmap>
13
14#include "Options.h"
15#include "kstarsdata.h" // MINZOOM
16#include "skymap.h"
17#include "projections/projector.h"
18
19//---------------------------------------------------------------------------//
20// A Little data container class
21//---------------------------------------------------------------------------//
22
23typedef struct LabelRun
24{
25 LabelRun(int s, int e) : start(s), end(e) {}
26 int start;
27 int end;
28
29} LabelRun;
30
31//----- Now for the main event ----------------------------------------------//
32
33//----- Static Methods ------------------------------------------------------//
34
35SkyLabeler *SkyLabeler::pinstance = nullptr;
36
37SkyLabeler *SkyLabeler::Instance()
38{
39 if (!pinstance)
40 pinstance = new SkyLabeler();
41 return pinstance;
42}
43
45{
46#ifndef KSTARS_LITE
47 QFont font(m_p.font());
48#else
49 QFont font(m_stdFont);
50#endif
51 int deltaSize = 0;
52 if (Options::zoomFactor() < 2.0 * MINZOOM)
53 deltaSize = 2;
54 else if (Options::zoomFactor() < 10.0 * MINZOOM)
55 deltaSize = 1;
56
57#ifndef KSTARS_LITE
58 if (deltaSize)
59 {
60 font.setPointSize(font.pointSize() - deltaSize);
61 m_p.setFont(font);
62 }
63#else
64 if (deltaSize)
65 {
66 font.setPointSize(font.pointSize() - deltaSize);
67 }
68 if (m_drawFont.pointSize() != font.pointSize())
69 {
70 m_drawFont = font;
71 }
72#endif
73}
74
76{
77 double offset = dms::PI * Options::zoomFactor() / 10800.0 / 3600.0;
78 return 4.0 + offset * 0.5;
79}
80
81//----- Constructor ---------------------------------------------------------//
82
83SkyLabeler::SkyLabeler()
84 : m_fontMetrics(QFont()), m_picture(-1), labelList(NUM_LABEL_TYPES)
85{
86#ifdef KSTARS_LITE
87 //Painter is needed to get default font and we use it only once to have only one warning
88 m_stdFont = QFont();
89
90//For some reason there is no point size in default font on Android
91#ifdef ANDROID
92 m_stdFont.setPointSize(16);
93#else
94 m_stdFont.setPointSize(m_stdFont.pointSize()+2);
95#endif
96
97#endif
98}
99
100SkyLabeler::~SkyLabeler()
101{
102 for (auto &row : screenRows)
103 {
104 for (auto &item : *row)
105 {
106 delete item;
107 }
108 delete row;
109 }
110}
111
112bool SkyLabeler::drawGuideLabel(QPointF &o, const QString &text, double angle)
113{
114 // Create bounding rectangle by rotating the (height x width) rectangle
115 qreal h = m_fontMetrics.height();
116 qreal w = m_fontMetrics.averageCharWidth() * text.size();
117 qreal s = sin(angle * dms::PI / 180.0);
118 qreal c = cos(angle * dms::PI / 180.0);
119
120 qreal w2 = w / 2.0;
121
122 qreal top, bot, left, right;
123
124 // These numbers really do depend on the sign of the angle like this
125 if (angle >= 0.0)
126 {
127 top = o.y() - s * w2;
128 bot = o.y() + c * h + s * w2;
129 left = o.x() - c * w2 - s * h;
130 right = o.x() + c * w2;
131 }
132 else
133 {
134 top = o.y() + s * w2;
135 bot = o.y() + c * h - s * w2;
136 left = o.x() - c * w2;
137 right = o.x() + c * w2 - s * h;
138 }
139
140 // return false if label would overlap existing label
141 if (!markRegion(left, right, top, bot))
142 return false;
143
144 // for debugging the bounding rectangle:
145 //psky.drawLine( QPointF( left, top ), QPointF( right, top ) );
146 //psky.drawLine( QPointF( right, top ), QPointF( right, bot ) );
147 //psky.drawLine( QPointF( right, bot ), QPointF( left, bot ) );
148 //psky.drawLine( QPointF( left, bot ), QPointF( left, top ) );
149
150 // otherwise draw the label and return true
151 m_p.save();
152 m_p.translate(o);
153
154 m_p.rotate(angle); //rotate the coordinate system
155 m_p.drawText(QPointF(-w2, h), text);
156 m_p.restore(); //reset coordinate system
157
158 return true;
159}
160
162 const qreal padding_factor)
163{
164 QString sLabel = obj->labelString();
165 if (sLabel.isEmpty())
166 return false;
167
168 double offset = obj->labelOffset();
169 QPointF p(_p.x() + offset, _p.y() + offset);
170
171 if (!markText(p, sLabel, padding_factor))
172 {
173 return false;
174 }
175 else
176 {
177 double factor = log(Options::zoomFactor() / 750.0);
178 double newPointSize = qBound(12.0, factor * m_stdFont.pointSizeF(), 18.0) * (1.0 + 0.7 * Options::labelFontScaling()/100.0);
179 QFont zoomFont(m_p.font());
180 zoomFont.setPointSizeF(newPointSize);
181 m_p.setFont(zoomFont);
182 m_p.drawText(p, sLabel);
183 return true;
184 }
185}
186
187void SkyLabeler::setFont(const QFont &font)
188{
189#ifndef KSTARS_LITE
190 m_p.setFont(font);
191#else
192 m_drawFont = font;
193#endif
194 m_fontMetrics = QFontMetrics(font);
195}
196
197void SkyLabeler::setPen(const QPen &pen)
198{
199#ifdef KSTARS_LITE
200 Q_UNUSED(pen);
201#else
202 m_p.setPen(pen);
203#endif
204}
205
207{
208#ifndef KSTARS_LITE
209 QFont font(m_p.font());
210#else
211 QFont font(m_drawFont);
212#endif
213 font.setPointSize(font.pointSize() - delta);
214 setFont(font);
215}
216
218{
219 setFont(m_stdFont);
220}
221
223{
224 setFont(m_skyFont);
225}
226
227void SkyLabeler::getMargins(const QString &text, float *left, float *right, float *top, float *bot)
228{
229 float height = m_fontMetrics.height();
230 float width = m_fontMetrics.averageCharWidth() * text.size();
231 float sideMargin = m_fontMetrics.averageCharWidth() * 2 + width / 2.0;
232
233 // Create the margins within which it is okay to draw the label
234 double winHeight;
235 double winWidth;
236#ifdef KSTARS_LITE
237 winHeight = SkyMapLite::Instance()->height();
238 winWidth = SkyMapLite::Instance()->width();
239#else
240 winHeight = m_p.window().height();
241 winWidth = m_p.window().width();
242#endif
243
244 *right = winWidth - sideMargin;
245 *left = sideMargin;
246 *top = height;
247 *bot = winHeight - 2.0 * height;
248}
249
251{
252 // ----- Set up Projector ---
253 m_proj = skyMap->projector();
254 // ----- Set up Painter -----
255 if (m_p.isActive())
256 m_p.end();
257 m_picture = QPicture();
258 m_p.begin(&m_picture);
259 //This works around BUG 10496 in Qt
260 m_p.drawPoint(0, 0);
261 m_p.drawPoint(skyMap->width() + 1, skyMap->height() + 1);
262 // ----- Set up Zoom Dependent Font -----
263
264 m_stdFont = QFont(m_p.font());
265 setZoomFont();
266 m_skyFont = m_p.font();
267 m_fontMetrics = QFontMetrics(m_skyFont);
268 m_minDeltaX = (int) m_fontMetrics.averageCharWidth() * 5;
269
270 // ----- Set up Zoom Dependent Offset -----
271 m_offset = SkyLabeler::ZoomOffset();
272
273 // ----- Prepare Virtual Screen -----
274 m_yScale = (m_fontMetrics.height() + 1.0);
275
276 int maxY = int(skyMap->height() / m_yScale);
277 if (maxY < 1)
278 maxY = 1; // prevents a crash below?
279
280 int m_maxX = skyMap->width();
281 m_size = (maxY + 1) * m_maxX;
282
283 // Resize if needed:
284 if (maxY > m_maxY)
285 {
286 screenRows.resize(m_maxY);
287 for (int y = m_maxY; y <= maxY; y++)
288 {
289 screenRows.append(new LabelRow());
290 }
291 //printf("resize: %d -> %d, size:%d\n", m_maxY, maxY, screenRows.size());
292 }
293
294 // Clear all pre-existing rows as needed
295
296 int minMaxY = (maxY < m_maxY) ? maxY : m_maxY;
297
298 for (int y = 0; y <= minMaxY; y++)
299 {
300 LabelRow *row = screenRows[y];
301
302 for (auto &item : *row)
303 {
304 delete item;
305 }
306 row->clear();
307 }
308
309 // never decrease m_maxY:
310 if (m_maxY < maxY)
311 m_maxY = maxY;
312
313 // reset the counters
314 m_marks = m_hits = m_misses = m_elements = 0;
315
316 //----- Clear out labelList -----
317 for (auto &item : labelList)
318 {
319 item.clear();
320 }
321}
322
323#ifdef KSTARS_LITE
325{
326 SkyMapLite *skyMap = SkyMapLite::Instance();
327 // ----- Set up Projector ---
328 m_proj = skyMap->projector();
329
330 //m_stdFont was moved to constructor
331 setZoomFont();
332 m_skyFont = m_drawFont;
333 m_fontMetrics = QFontMetrics(m_skyFont);
334 m_minDeltaX = (int)m_fontMetrics.width("MMMMM");
335 // ----- Set up Zoom Dependent Offset -----
336 m_offset = ZoomOffset();
337
338 // ----- Prepare Virtual Screen -----
339 m_yScale = (m_fontMetrics.height() + 1.0);
340
341 int maxY = int(skyMap->height() / m_yScale);
342 if (maxY < 1)
343 maxY = 1; // prevents a crash below?
344
345 int m_maxX = skyMap->width();
346 m_size = (maxY + 1) * m_maxX;
347
348 // Resize if needed:
349 if (maxY > m_maxY)
350 {
351 screenRows.resize(m_maxY);
352 for (int y = m_maxY; y <= maxY; y++)
353 {
354 screenRows.append(new LabelRow());
355 }
356 //printf("resize: %d -> %d, size:%d\n", m_maxY, maxY, screenRows.size());
357 }
358
359 // Clear all pre-existing rows as needed
360
361 int minMaxY = (maxY < m_maxY) ? maxY : m_maxY;
362
363 for (int y = 0; y <= minMaxY; y++)
364 {
365 LabelRow *row = screenRows[y];
366 for (int i = 0; i < row->size(); i++)
367 {
368 delete row->at(i);
369 }
370 row->clear();
371 }
372
373 // never decrease m_maxY:
374 if (m_maxY < maxY)
375 m_maxY = maxY;
376
377 // reset the counters
378 m_marks = m_hits = m_misses = m_elements = 0;
379
380 //----- Clear out labelList -----
381 for (int i = 0; i < labelList.size(); i++)
382 {
383 labelList[i].clear();
384 }
385}
386#endif
387
389{
390 //FIXME: need a better soln. Apparently starting a painter
391 //clears the picture.
392 // But it's not like that's something that should be in the docs, right?
393 // No, that's definitely better to leave to people to figure out on their own.
394 if (m_p.isActive())
395 {
396 m_p.end();
397 }
398 m_picture.play(&p); //can't replay while it's being painted on
399 //this is also undocumented btw.
400 //m_p.begin(&m_picture);
401}
402
403// We use Run Length Encoding to hold the information instead of an array of
404// chars. This is both faster and smaller but the code is more complicated.
405//
406// This code is easy to break and hard to fix.
407
408bool SkyLabeler::markText(const QPointF &p, const QString &text, qreal padding_factor)
409{
410 static const auto ramp_zoom = log10(MAXZOOM) + log10(0.3);
411
412 if (padding_factor != 1)
413 {
414 padding_factor =
415 (1 - ((std::min(log10(Options::zoomFactor()), ramp_zoom)) / ramp_zoom)) *
416 padding_factor +
417 1;
418 }
419
420 const qreal maxX = p.x() + m_fontMetrics.averageCharWidth() * text.size() * padding_factor;
421 const qreal minY = p.y() - m_fontMetrics.height() * padding_factor;
422 return markRegion(p.x(), maxX, p.y(), minY);
423}
424
425bool SkyLabeler::markRegion(qreal left, qreal right, qreal top, qreal bot)
426{
427 if (m_maxY < 1)
428 {
429 if (!m_errors++)
430 qDebug() << Q_FUNC_INFO << QString("Someone forgot to reset the SkyLabeler!");
431 return true;
432 }
433
434 // setup x coordinates of rectangular region
435 int minX = int(left);
436 int maxX = int(right);
437 if (maxX < minX)
438 {
439 maxX = minX;
440 minX = int(right);
441 }
442
443 // setup y coordinates
444 int maxY = int(bot / m_yScale);
445 int minY = int(top / m_yScale);
446
447 if (maxY < 0)
448 maxY = 0;
449 if (maxY > m_maxY)
450 maxY = m_maxY;
451 if (minY < 0)
452 minY = 0;
453 if (minY > m_maxY)
454 minY = m_maxY;
455
456 if (maxY < minY)
457 {
458 int temp = maxY;
459 maxY = minY;
460 minY = temp;
461 }
462
463 // check to see if we overlap any existing label
464 // We must check all rows before we start marking
465 for (int y = minY; y <= maxY; y++)
466 {
467 LabelRow *row = screenRows[y];
468 int i;
469 for (i = 0; i < row->size(); i++)
470 {
471 if (row->at(i)->end < minX)
472 continue; // skip past these
473 if (row->at(i)->start > maxX)
474 break;
475 m_misses++;
476 return false;
477 }
478 }
479
480 m_hits++;
481 m_marks += (maxX - minX + 1) * (maxY - minY + 1);
482
483 // Okay, there was no overlap so let's insert the current rectangle into
484 // screenRows.
485
486 for (int y = minY; y <= maxY; y++)
487 {
488 LabelRow *row = screenRows[y];
489
490 // Simplest case: an empty row
491 if (row->size() < 1)
492 {
493 row->append(new LabelRun(minX, maxX));
494 m_elements++;
495 continue;
496 }
497
498 // Find out our place in the universe (or row).
499 // H'mm. Maybe we could cache these numbers above.
500 int i;
501 for (i = 0; i < row->size(); i++)
502 {
503 if (row->at(i)->end >= minX)
504 break;
505 }
506
507 // i now points to first label PAST ours
508
509 // if we are first, append or merge at start of list
510 if (i == 0)
511 {
512 if (row->at(0)->start - maxX < m_minDeltaX)
513 {
514 row->at(0)->start = minX;
515 }
516 else
517 {
518 row->insert(0, new LabelRun(minX, maxX));
519 m_elements++;
520 }
521 continue;
522 }
523
524 // if we are past the last label, merge or append at end
525 else if (i == row->size())
526 {
527 if (minX - row->at(i - 1)->end < m_minDeltaX)
528 {
529 row->at(i - 1)->end = maxX;
530 }
531 else
532 {
533 row->append(new LabelRun(minX, maxX));
534 m_elements++;
535 }
536 continue;
537 }
538
539 // if we got here, we must insert or merge the new label
540 // between [i-1] and [i]
541
542 bool mergeHead = (minX - row->at(i - 1)->end < m_minDeltaX);
543 bool mergeTail = (row->at(i)->start - maxX < m_minDeltaX);
544
545 // double merge => combine all 3 into one
546 if (mergeHead && mergeTail)
547 {
548 row->at(i - 1)->end = row->at(i)->end;
549 delete row->at(i);
550 row->removeAt(i);
551 m_elements--;
552 }
553
554 // Merge label with [i-1]
555 else if (mergeHead)
556 {
557 row->at(i - 1)->end = maxX;
558 }
559
560 // Merge label with [i]
561 else if (mergeTail)
562 {
563 row->at(i)->start = minX;
564 }
565
566 // insert between the two
567 else
568 {
569 row->insert(i, new LabelRun(minX, maxX));
570 m_elements++;
571 }
572 }
573
574 return true;
575}
576
578{
579 bool visible = false;
580 QPointF p = m_proj->toScreen(obj, true, &visible);
581 if (!visible || !m_proj->onScreen(p) || obj->translatedName().isEmpty())
582 return;
583 labelList[(int)type].append(SkyLabel(p, obj));
584}
585
586#ifdef KSTARS_LITE
587void SkyLabeler::addLabel(SkyObject *obj, QPointF pos, label_t type)
588{
589 labelList[(int)type].append(SkyLabel(pos, obj));
590}
591#endif
592
594{
595 KStarsData *data = KStarsData::Instance();
596
597 resetFont();
598 m_p.setPen(QColor(data->colorScheme()->colorNamed("PNameColor")));
599 drawQueuedLabelsType(PLANET_LABEL);
600
601 if (labelList[SATURN_MOON_LABEL].size() > 0)
602 {
603 shrinkFont(2);
604 drawQueuedLabelsType(SATURN_MOON_LABEL);
605 resetFont();
606 }
607
608 if (labelList[JUPITER_MOON_LABEL].size() > 0)
609 {
610 shrinkFont(2);
611 drawQueuedLabelsType(JUPITER_MOON_LABEL);
612 resetFont();
613 }
614
615 // No colors for these fellas? Just following planets along?
616 drawQueuedLabelsType(ASTEROID_LABEL);
617 drawQueuedLabelsType(COMET_LABEL);
618
619 m_p.setPen(QColor(data->colorScheme()->colorNamed("SatLabelColor")));
620 drawQueuedLabelsType(SATELLITE_LABEL);
621
622 // Whelp we're here and we don't have a Rude Label color?
623 // Will just set it to Planet color since this is how it used to be!!
624 m_p.setPen(QColor(data->colorScheme()->colorNamed("PNameColor")));
625 LabelList list = labelList[RUDE_LABEL];
626
627 for (const auto &item : list)
628 {
629 drawRudeNameLabel(item.obj, item.o);
630 }
631}
632
634{
635 LabelList list = labelList[type];
636
637 for (const auto &item : list)
638 {
639 drawNameLabel(item.obj, item.o);
640 }
641}
642
643//Rude name labels don't check for collisions with other labels,
644//these get drawn no matter what. Transient labels are rude labels.
645//To mitigate confusion from possibly "underlapping" labels, paint a
646//semi-transparent background.
648{
649 QString sLabel = obj->labelString();
650 double offset = obj->labelOffset();
651 QRectF rect = m_p.fontMetrics().boundingRect(sLabel);
652 rect.moveTo(p.x() + offset, p.y() + offset);
653
654 //Interestingly, the fontMetric boundingRect isn't where you might think...
655 //We need to tweak rect to get the BG rectangle rect2
656 QRectF rect2 = rect;
657 rect2.moveTop(rect.top() - 0.6 * rect.height());
658 rect2.setHeight(0.8 * rect.height());
659
660 //FIXME: Implement label background options
661 QColor color(KStarsData::Instance()->colorScheme()->colorNamed("SkyColor"));
662 color.setAlpha(m_p.pen().color().alpha()); //same transparency for the text and the background
663 m_p.fillRect(rect2, QBrush(color));
664 m_p.drawText(rect.topLeft(), sLabel);
665}
666
667//----- Diagnostic and information routines -----
668
670{
671 if (m_size == 0)
672 return 0.0;
673 return 100.0 * float(m_marks) / float(m_size);
674}
675
677{
678 if (m_hits == 0)
679 return 0.0;
680 return 100.0 * float(m_hits) / (float(m_hits + m_misses));
681}
682
684{
685 printf("SkyLabeler:\n");
686 printf(" fillRatio=%.1f%%\n", fillRatio());
687 printf(" hits=%d misses=%d ratio=%.1f%%\n", m_hits, m_misses, hitRatio());
688 printf(" yScale=%.1f maxY=%d\n", m_yScale, m_maxY);
689
690 printf(" screenRows=%d elements=%d virtualSize=%.1f Kbytes\n", screenRows.size(), m_elements,
691 float(m_size) / 1024.0);
692
693// static const char *labelName[NUM_LABEL_TYPES];
694//
695// labelName[STAR_LABEL] = "Star";
696// labelName[ASTEROID_LABEL] = "Asteroid";
697// labelName[COMET_LABEL] = "Comet";
698// labelName[PLANET_LABEL] = "Planet";
699// labelName[JUPITER_MOON_LABEL] = "Jupiter Moon";
700// labelName[SATURN_MOON_LABEL] = "Saturn Moon";
701// labelName[DEEP_SKY_LABEL] = "Deep Sky Object";
702// labelName[CONSTEL_NAME_LABEL] = "Constellation Name";
703//
704// for (int i = 0; i < NUM_LABEL_TYPES; i++)
705// {
706// printf(" %20ss: %d\n", labelName[i], labelList[i].size());
707// }
708//
709// // Check for errors in the data structure
710// for (int y = 0; y <= m_maxY; y++)
711// {
712// LabelRow *row = screenRows[y];
713// int size = row->size();
714// if (size < 2)
715// continue;
716//
717// bool error = false;
718// for (int i = 1; i < size; i++)
719// {
720// if (row->at(i - 1)->end > row->at(i)->start)
721// error = true;
722// }
723// if (!error)
724// continue;
725//
726// printf("ERROR: %3d: ", y);
727// for (int i = 0; i < row->size(); i++)
728// {
729// printf("(%d, %d) ", row->at(i)->start, row->at(i)->end);
730// }
731// printf("\n");
732// }
733}
QColor colorNamed(const QString &name) const
Retrieve a color by name.
KStarsData is the backbone of KStars.
Definition kstarsdata.h:74
ColorScheme * colorScheme()
Definition kstarsdata.h:174
QPointF toScreen(const SkyPoint *o, bool oRefract=true, bool *onVisibleHemisphere=nullptr) const
This is exactly the same as toScreenVec but it returns a QPointF.
Definition projector.cpp:93
bool onScreen(const QPointF &p) const
Check whether the projected point is on-screen.
Definition projector.cpp:98
The purpose of this class is to prevent labels from overlapping.
Definition skylabeler.h:99
float fillRatio()
diagnostic.
bool markText(const QPointF &p, const QString &text, qreal padding_factor=1)
tells the labeler the location and text of a label you want to draw.
void resetFont()
sets the font in SkyLabeler and in psky back to the zoom dependent value that was set in reset().
void shrinkFont(int delta)
decreases the size of the font in psky and in the SkyLabeler by the delta points.
void setZoomFont()
adjusts the font in psky to be smaller if we are zoomed out.
bool markRegion(qreal left, qreal right, qreal top, qreal bot)
Works just like markText() above but for an arbitrary rectangular region bounded by top,...
void drawQueuedLabels()
draws the labels stored in all the buffers.
void setFont(const QFont &font)
tells the labeler the font you will be using so it can figure out the height and width of the labels.
void reset(SkyMap *skyMap)
clears the virtual screen (if needed) and resizes the virtual screen (if needed) to match skyMap.
void getMargins(const QString &text, float *left, float *right, float *top, float *bot)
sets four margins for help in keeping labels entirely on the screen.
bool drawGuideLabel(QPointF &o, const QString &text, double angle)
Tries to draw the text at the position and angle specified.
void addLabel(SkyObject *obj, label_t type)
queues the label in the "type" buffer for later drawing.
void setPen(const QPen &pen)
sets the pen used for drawing labels on the sky.
static double ZoomOffset()
returns the zoom dependent label offset.
float hitRatio()
diagnostic, the number of times mark() returned true divided by the total number of times mark was ca...
void useStdFont()
sets the font in SkyLabeler and in psky to the font psky had originally when reset() was called.
void printInfo()
diagnostic, prints some brief statistics to the console.
void drawQueuedLabelsType(SkyLabeler::label_t type)
a convenience routine that draws all the labels from a single buffer.
void draw(QPainter &p)
KStars Lite version of the function above.
void drawRudeNameLabel(SkyObject *obj, const QPointF &_p)
draw the object's name label on the map, without checking for overlap with other labels.
bool drawNameLabel(SkyObject *obj, const QPointF &_p, const qreal padding_factor=1)
Tries to draw a label for an object.
This is the main item that displays all SkyItems.
Definition skymaplite.h:59
const Projector * projector() const
Get the current projector.
Definition skymaplite.h:323
This is the canvas on which the sky is painted.
Definition skymap.h:54
const Projector * projector() const
Get the current projector.
Definition skymap.h:300
Provides all necessary information about an object in the sky: its coordinates, name(s),...
Definition skyobject.h:42
QString translatedName() const
Definition skyobject.h:149
virtual QString labelString() const
virtual double labelOffset() const
static constexpr double PI
PI is a const static member; it's public so that it can be used anywhere, as long as dms....
Definition dms.h:385
int alpha() const const
void setAlpha(int alpha)
int pointSize() const const
qreal pointSizeF() const const
void setPointSize(int pointSize)
void setPointSizeF(qreal pointSize)
QRect boundingRect(QChar ch) const const
qreal averageCharWidth() const const
qreal height() const const
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
void clear()
iterator insert(const_iterator before, parameter_type value)
void removeAt(qsizetype i)
qsizetype size() const const
bool begin(QPaintDevice *device)
void drawPoint(const QPoint &position)
void drawText(const QPoint &position, const QString &text)
bool end()
void fillRect(const QRect &rectangle, QGradient::Preset preset)
const QFont & font() const const
QFontMetrics fontMetrics() const const
bool isActive() const const
const QPen & pen() const const
void restore()
void rotate(qreal angle)
void save()
void setFont(const QFont &font)
void setPen(Qt::PenStyle style)
void translate(const QPoint &offset)
QRect window() const const
QColor color() const const
bool play(QPainter *painter)
qreal x() const const
qreal y() const const
int height() const const
int width() const const
qreal height() const const
void moveTo(const QPointF &position)
void moveTop(qreal y)
void setHeight(qreal height)
qreal top() const const
QPointF topLeft() const const
bool isEmpty() const const
qsizetype size() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:16:41 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.