24#include <QFontMetricsF>
30 bool isNullSize =
false;
31 const QFont font = format.
scaledFont( context, scaleFactor, &isNullSize );
39 double heightLabelMode = 0;
40 double heightPointRectMode = 0;
41 const int blockSize = document.
size();
42 res.mFragmentFonts.reserve( blockSize );
43 double currentLabelBaseline = 0;
44 double currentPointBaseline = 0;
45 double currentRectBaseline = 0;
46 double lastLineLeading = 0;
48 double heightVerticalOrientation = 0;
50 QVector < double > blockVerticalLineSpacing;
52 for (
int blockIndex = 0; blockIndex < blockSize; blockIndex++ )
57 double blockHeightUsingAscentDescent = 0;
58 double blockHeightUsingLineSpacing = 0;
59 double blockHeightVerticalOrientation = 0;
60 const int fragmentSize = block.
size();
62 double maxBlockAscent = 0;
63 double maxBlockDescent = 0;
64 double maxLineSpacing = 0;
65 double maxBlockLeading = 0;
66 double maxBlockMaxWidth = 0;
68 QList< QFont > fragmentFonts;
69 fragmentFonts.reserve( fragmentSize );
70 for (
int fragmentIndex = 0; fragmentIndex < fragmentSize; ++fragmentIndex )
74 QFont updatedFont = font;
76 const QFontMetricsF fm( updatedFont );
78 const double fragmentWidth = fm.horizontalAdvance( fragment.
text() ) / scaleFactor;
79 const double fragmentHeightUsingAscentDescent = ( fm.ascent() + fm.descent() ) / scaleFactor;
80 const double fragmentHeightUsingLineSpacing = fm.lineSpacing() / scaleFactor;
83 blockHeightUsingAscentDescent = std::max( blockHeightUsingAscentDescent, fragmentHeightUsingAscentDescent );
84 blockHeightUsingLineSpacing = std::max( blockHeightUsingLineSpacing, fragmentHeightUsingLineSpacing );
85 maxBlockAscent = std::max( maxBlockAscent, fm.ascent() / scaleFactor );
86 maxBlockDescent = std::max( maxBlockDescent, fm.descent() / scaleFactor );
87 maxBlockMaxWidth = std::max( maxBlockMaxWidth, fm.maxWidth() / scaleFactor );
89 if ( ( fm.lineSpacing() / scaleFactor ) > maxLineSpacing )
91 maxLineSpacing = fm.lineSpacing() / scaleFactor;
92 maxBlockLeading = fm.leading() / scaleFactor;
95 fragmentFonts << updatedFont;
97 const double verticalOrientationFragmentHeight = fragmentIndex == 0 ? ( fm.ascent() / scaleFactor * fragment.
text().size() + ( fragment.
text().size() - 1 ) * updatedFont.letterSpacing() / scaleFactor )
98 : ( fragment.
text().size() * ( fm.ascent() / scaleFactor + updatedFont.letterSpacing() / scaleFactor ) );
99 blockHeightVerticalOrientation += verticalOrientationFragmentHeight;
102 if ( blockIndex == 0 )
106 res.mFirstLineAscentOffset = 0.25 * maxBlockAscent;
107 res.mLastLineAscentOffset = res.mFirstLineAscentOffset;
108 const double lineHeight = ( maxBlockAscent + maxBlockDescent );
113 currentLabelBaseline = -res.mFirstLineAscentOffset;
116 currentRectBaseline = -res.mFirstLineAscentOffset + lineHeight - 1 ;
119 currentPointBaseline = 0;
121 heightLabelMode += blockHeightUsingAscentDescent;
122 heightPointRectMode += blockHeightUsingAscentDescent;
129 currentLabelBaseline += thisLineHeightUsingAscentDescent;
130 currentRectBaseline += thisLineHeightUsingLineSpacing;
131 currentPointBaseline += thisLineHeightUsingLineSpacing;
133 heightLabelMode += thisLineHeightUsingAscentDescent;
134 heightPointRectMode += thisLineHeightUsingLineSpacing;
135 if ( blockIndex == blockSize - 1 )
136 res.mLastLineAscentOffset = 0.25 * maxBlockAscent;
141 res.mBlockHeights << blockHeightUsingLineSpacing;
144 heightVerticalOrientation = std::max( heightVerticalOrientation, blockHeightVerticalOrientation );
146 res.mFragmentFonts << fragmentFonts;
147 res.mBaselineOffsetsLabelMode << currentLabelBaseline;
148 res.mBaselineOffsetsPointMode << currentPointBaseline;
149 res.mBaselineOffsetsRectMode << currentRectBaseline;
150 res.mBlockMaxDescent << maxBlockDescent;
151 res.mBlockMaxCharacterWidth << maxBlockMaxWidth;
153 if ( blockIndex > 0 )
154 lastLineLeading = maxBlockLeading;
157 heightLabelMode -= lastLineLeading;
158 heightPointRectMode -= lastLineLeading;
160 res.mDocumentSizeLabelMode = QSizeF( width, heightLabelMode );
161 res.mDocumentSizePointRectMode = QSizeF( width, heightPointRectMode );
164 if ( !res.mBaselineOffsetsLabelMode.isEmpty() )
166 const double labelModeBaselineAdjust = res.mBaselineOffsetsLabelMode.constLast() + res.mLastLineAscentOffset;
167 const double pointModeBaselineAdjust = res.mBaselineOffsetsPointMode.constLast();
168 for (
int i = 0; i < blockSize; ++i )
170 res.mBaselineOffsetsLabelMode[i] -= labelModeBaselineAdjust;
171 res.mBaselineOffsetsPointMode[i] -= pointModeBaselineAdjust;
175 if ( !res.mBlockMaxCharacterWidth.isEmpty() )
177 QList< double > adjustedRightToLeftXOffsets;
178 double currentOffset = 0;
179 const int size = res.mBlockMaxCharacterWidth.size();
181 double widthVerticalOrientation = 0;
182 for (
int i = 0; i < size; ++i )
184 const double rightToLeftBlockMaxCharacterWidth = res.mBlockMaxCharacterWidth[size - 1 - i ];
185 const double rightToLeftLineSpacing = blockVerticalLineSpacing[ size - 1 - i ];
187 adjustedRightToLeftXOffsets << currentOffset;
188 currentOffset += rightToLeftLineSpacing;
191 widthVerticalOrientation += rightToLeftBlockMaxCharacterWidth;
193 widthVerticalOrientation += rightToLeftLineSpacing;
195 std::reverse( adjustedRightToLeftXOffsets.begin(), adjustedRightToLeftXOffsets.end() );
196 res.mVerticalOrientationXOffsets = adjustedRightToLeftXOffsets;
198 res.mDocumentSizeVerticalOrientation = QSizeF( widthVerticalOrientation, heightVerticalOrientation );
206 switch ( orientation )
208 case Qgis::TextOrientation::Horizontal:
211 case Qgis::TextLayoutMode::Rectangle:
213 return mDocumentSizePointRectMode;
215 case Qgis::TextLayoutMode::Labeling:
216 return mDocumentSizeLabelMode;
220 case Qgis::TextOrientation::Vertical:
221 return mDocumentSizeVerticalOrientation;
222 case Qgis::TextOrientation::RotationBased:
231 return mBlockWidths.value( blockIndex );
236 return mBlockHeights.value( blockIndex );
243 case Qgis::TextLayoutMode::Rectangle:
244 return mBaselineOffsetsRectMode.value( blockIndex );
246 return mBaselineOffsetsPointMode.value( blockIndex );
247 case Qgis::TextLayoutMode::Labeling:
248 return mBaselineOffsetsLabelMode.value( blockIndex );
255 return mVerticalOrientationXOffsets.value( blockIndex );
260 return mBlockMaxCharacterWidth.value( blockIndex );
265 return mBlockMaxDescent.value( blockIndex );
270 return mFragmentFonts.value( blockIndex ).value( fragmentIndex );
TextLayoutMode
Text layout modes.
@ Point
Text at point of origin layout mode.
TextOrientation
Text orientations.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
Represents a block of text consisting of one or more QgsTextFragment objects.
int size() const
Returns the number of fragments in the block.
const QgsTextFragment & at(int index) const
Returns the fragment at the specified index.
void updateFontForFormat(QFont &font, const QgsRenderContext &context, double scaleFactor=1.0) const
Updates the specified font in place, applying character formatting options which are applicable on a ...
Contains pre-calculated metrics of a QgsTextDocument.
double verticalOrientationXOffset(int blockIndex) const
Returns the vertical orientation x offset for the specified block.
double blockMaximumDescent(int blockIndex) const
Returns the maximum descent encountered in the specified block.
QSizeF documentSize(Qgis::TextLayoutMode mode, Qgis::TextOrientation orientation) const
Returns the overall size of the document.
QFont fragmentFont(int blockIndex, int fragmentIndex) const
Returns the calculated font for the fragment at the specified block and fragment indices.
double blockMaximumCharacterWidth(int blockIndex) const
Returns the maximum character width for the specified block.
double baselineOffset(int blockIndex, Qgis::TextLayoutMode mode) const
Returns the offset from the top of the document to the text baseline for the given block index.
static QgsTextDocumentMetrics calculateMetrics(const QgsTextDocument &document, const QgsTextFormat &format, const QgsRenderContext &context, double scaleFactor=1.0)
Returns precalculated text metrics for a text document, when rendered using the given base format and...
double blockHeight(int blockIndex) const
Returns the height of the block at the specified index.
double blockWidth(int blockIndex) const
Returns the width of the block at the specified index.
Represents a document consisting of one or more QgsTextBlock objects.
const QgsTextBlock & at(int index) const
Returns the block at the specified index.
int size() const
Returns the number of blocks in the document.
Container for all settings relating to text rendering.
double lineHeight() const
Returns the line height for text.
QFont scaledFont(const QgsRenderContext &context, double scaleFactor=1.0, bool *isZeroSize=nullptr) const
Returns a font with the size scaled to match the format's size settings (including units and map unit...
QgsUnitTypes::RenderUnit lineHeightUnit() const
Returns the units for the line height for text.
Stores a fragment of text along with formatting overrides to be used when rendering the fragment.
QString text() const
Returns the text content of the fragment.
const QgsTextCharacterFormat & characterFormat() const
Returns the character formatting for the fragment.
@ RenderPercentage
Percentage of another measurement (e.g., canvas size, feature size)
#define BUILTIN_UNREACHABLE