QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgstextlabelfeature.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgstextlabelfeature.cpp
3  ---------------------
4  begin : December 2015
5  copyright : (C) 2015 by Martin Dobias
6  email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgstextlabelfeature.h"
17 
18 #include "qgsgeometry.h"
19 #include "qgspallabeling.h"
20 #include "qgsmaptopixel.h"
21 #include "pal/feature.h"
22 #include "qgstextcharacterformat.h"
23 #include "qgstextfragment.h"
24 #include "qgstextblock.h"
25 
27  : QgsLabelFeature( id, std::move( geometry ), size )
28 {
29  mDefinedFont = QFont();
30 }
31 
33 
34 QString QgsTextLabelFeature::text( int partId ) const
35 {
36  if ( partId == -1 )
37  return mLabelText;
38  else
39  return mTextMetrics->grapheme( partId );
40 }
41 
43 {
44  return mTextMetrics.has_value() ? mTextMetrics->graphemeFormat( partId ) : QgsTextCharacterFormat();
45 }
46 
48 {
49  return mTextMetrics.has_value() && partId < mTextMetrics->graphemeFormatCount();
50 }
51 
52 void QgsTextLabelFeature::setFontMetrics( const QFontMetricsF &metrics )
53 {
54  mFontMetrics = metrics; // duplicate metrics for when drawing label
55 }
56 
57 QgsPrecalculatedTextMetrics QgsTextLabelFeature::calculateTextMetrics( const QgsMapToPixel *xform, const QFontMetricsF &fontMetrics, double letterSpacing, double wordSpacing, const QString &text, QgsTextDocument *document )
58 {
59  // create label info!
60  const double mapScale = xform->mapUnitsPerPixel();
61  const double characterHeight = mapScale * fontMetrics.height();
62  QStringList graphemes;
63  QVector< QgsTextCharacterFormat > graphemeFormats;
64 
65  if ( document )
66  {
67  for ( const QgsTextBlock &block : std::as_const( *document ) )
68  {
69  for ( const QgsTextFragment &fragment : block )
70  {
71  const QStringList fragmentGraphemes = QgsPalLabeling::splitToGraphemes( fragment.text() );
72  for ( const QString &grapheme : fragmentGraphemes )
73  {
74  graphemes.append( grapheme );
75  graphemeFormats.append( fragment.characterFormat() );
76  }
77  }
78  }
79  }
80  else
81  {
82  //split string by valid grapheme boundaries - required for certain scripts (see #6883)
84  }
85 
86  QVector< double > characterWidths( graphemes.count() );
87  for ( int i = 0; i < graphemes.count(); i++ )
88  {
89  // reconstruct how Qt creates word spacing, then adjust per individual stored character
90  // this will allow PAL to create each candidate width = character width + correct spacing
91 
92  qreal wordSpaceFix = qreal( 0.0 );
93  if ( graphemes[i] == QLatin1String( " " ) )
94  {
95  // word spacing only gets added once at end of consecutive run of spaces, see QTextEngine::shapeText()
96  int nxt = i + 1;
97  wordSpaceFix = ( nxt < graphemes.count() && graphemes[nxt] != QLatin1String( " " ) ) ? wordSpacing : qreal( 0.0 );
98  }
99  // this workaround only works for clusters with a single character. Not sure how it should be handled
100  // with multi-character clusters.
101  if ( graphemes[i].length() == 1 &&
102  !qgsDoubleNear( fontMetrics.horizontalAdvance( QString( graphemes[i].at( 0 ) ) ), fontMetrics.horizontalAdvance( graphemes[i].at( 0 ) ) + letterSpacing ) )
103  {
104  // word spacing applied when it shouldn't be
105  wordSpaceFix -= wordSpacing;
106  }
107 
108  const double charWidth = fontMetrics.horizontalAdvance( QString( graphemes[i] ) ) + wordSpaceFix;
109  characterWidths[i] = mapScale * charWidth;
110  }
111 
112  QgsPrecalculatedTextMetrics res( graphemes, characterHeight, std::move( characterWidths ) );
113  res.setGraphemeFormats( graphemeFormats );
114  return res;
115 }
116 
118 {
119  return mDocument;
120 }
121 
123 {
125 }
QgsTextLabelFeature::setDocument
void setDocument(const QgsTextDocument &document)
Sets the document for the label.
Definition: qgstextlabelfeature.cpp:122
qgspallabeling.h
QgsTextLabelFeature::text
QString text(int partId) const
Returns the text component corresponding to a specified label part.
Definition: qgstextlabelfeature.cpp:34
QgsPrecalculatedTextMetrics::setGraphemeFormats
void setGraphemeFormats(const QVector< QgsTextCharacterFormat > &formats)
Sets the character formats associated with the text graphemes().
Definition: qgstextmetrics.h:79
QgsMapToPixel::mapUnitsPerPixel
double mapUnitsPerPixel() const
Returns the current map units per pixel.
Definition: qgsmaptopixel.h:229
QgsTextLabelFeature::~QgsTextLabelFeature
~QgsTextLabelFeature() override
Clean up.
QgsTextLabelFeature::hasCharacterFormat
bool hasCharacterFormat(int partId) const
Returns true if the feature contains specific character formatting for the part with matching ID.
Definition: qgstextlabelfeature.cpp:47
qgstextfragment.h
QgsTextLabelFeature::calculateTextMetrics
static QgsPrecalculatedTextMetrics calculateTextMetrics(const QgsMapToPixel *xform, const QFontMetricsF &fontMetrics, double letterSpacing, double wordSpacing, const QString &text=QString(), QgsTextDocument *document=nullptr)
Calculate text metrics for later retrieval via textMetrics().
Definition: qgstextlabelfeature.cpp:57
qgsmaptopixel.h
QgsTextLabelFeature::characterFormat
QgsTextCharacterFormat characterFormat(int partId) const
Returns the character format corresponding to the specified label part.
Definition: qgstextlabelfeature.cpp:42
QgsTextLabelFeature::mDefinedFont
QFont mDefinedFont
Font for rendering.
Definition: qgstextlabelfeature.h:165
QgsTextCharacterFormat
Stores information relating to individual character formatting.
Definition: qgstextcharacterformat.h:39
QgsTextLabelFeature::mFontMetrics
std::optional< QFontMetricsF > mFontMetrics
Metrics of the font for rendering.
Definition: qgstextlabelfeature.h:168
QgsTextLabelFeature::QgsTextLabelFeature
QgsTextLabelFeature(QgsFeatureId id, geos::unique_ptr geometry, QSizeF size)
Construct text label feature.
Definition: qgstextlabelfeature.cpp:26
geos::unique_ptr
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
Definition: qgsgeos.h:79
feature.h
QgsTextFragment
Stores a fragment of text along with formatting overrides to be used when rendering the fragment.
Definition: qgstextfragment.h:35
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2265
QgsLabelFeature::mLabelText
QString mLabelText
text of the label
Definition: qgslabelfeature.h:653
QgsTextLabelFeature::mDocument
QgsTextDocument mDocument
Definition: qgstextlabelfeature.h:173
qgstextcharacterformat.h
QgsTextLabelFeature::setFontMetrics
void setFontMetrics(const QFontMetricsF &metrics)
Sets the font metrics.
Definition: qgstextlabelfeature.cpp:52
QgsTextBlock
Represents a block of text consisting of one or more QgsTextFragment objects.
Definition: qgstextblock.h:35
qgsgeometry.h
QgsMapToPixel
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:38
QgsTextDocument
Represents a document consisting of one or more QgsTextBlock objects.
Definition: qgstextdocument.h:38
QgsTextLabelFeature::document
QgsTextDocument document() const
Returns the document for the label.
Definition: qgstextlabelfeature.cpp:117
QgsTextLabelFeature::mTextMetrics
std::optional< QgsPrecalculatedTextMetrics > mTextMetrics
Definition: qgstextlabelfeature.h:178
QgsPrecalculatedTextMetrics
Contains precalculated properties regarding text metrics for text to be renderered at a later stage.
Definition: qgstextmetrics.h:34
QgsLabelFeature
The QgsLabelFeature class describes a feature that should be used within the labeling engine....
Definition: qgslabelfeature.h:57
qgstextlabelfeature.h
qgstextblock.h
QgsFeatureId
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
QgsPalLabeling::splitToGraphemes
static QStringList splitToGraphemes(const QString &text)
Splits a text string to a list of graphemes, which are the smallest allowable character divisions in ...
Definition: qgspallabeling.cpp:3893