mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-11 00:04:09 -04:00
Add support for super and subscript HTML formatting in text renderer
This allows for either: - <sup>superscript</sup> / <sub>subscript</sub> components in text, where the text will be vertically super or subscript aligned and automatically sized to 2/3rd of the parent font size. Users can also set a fixed font size for the super/sub script by including css rules, e.g. <sup style="font-size:33pt">super</sup> - "vertical-align: super" or "vertical-align: sub" CSS formatting rules in any other HTML element Sponsored by OSGEO UK
This commit is contained in:
parent
79b809a585
commit
a7c39ffdc7
@ -49,6 +49,19 @@ Returns ``True`` if the metrics could not be calculated because the text format
|
|||||||
QSizeF documentSize( Qgis::TextLayoutMode mode, Qgis::TextOrientation orientation ) const;
|
QSizeF documentSize( Qgis::TextLayoutMode mode, Qgis::TextOrientation orientation ) const;
|
||||||
%Docstring
|
%Docstring
|
||||||
Returns the overall size of the document.
|
Returns the overall size of the document.
|
||||||
|
%End
|
||||||
|
|
||||||
|
QRectF outerBounds( Qgis::TextLayoutMode mode, Qgis::TextOrientation orientation ) const;
|
||||||
|
%Docstring
|
||||||
|
Returns the outer bounds of the document, which is the :py:func:`~QgsTextDocumentMetrics.documentSize` adjusted to account
|
||||||
|
for any text elements which fall outside of the usual document margins (such as super or
|
||||||
|
sub script elements)
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Currently this is only supported for the Qgis.TextLayoutMode.Labeling mode.
|
||||||
|
|
||||||
|
.. versionadded:: 3.30
|
||||||
%End
|
%End
|
||||||
|
|
||||||
double blockWidth( int blockIndex ) const;
|
double blockWidth( int blockIndex ) const;
|
||||||
@ -70,6 +83,14 @@ Returns the offset from the top of the document to the text baseline for the giv
|
|||||||
%Docstring
|
%Docstring
|
||||||
Returns the horizontal advance of the fragment at the specified block and fragment index.
|
Returns the horizontal advance of the fragment at the specified block and fragment index.
|
||||||
|
|
||||||
|
.. versionadded:: 3.30
|
||||||
|
%End
|
||||||
|
|
||||||
|
double fragmentVerticalOffset( int blockIndex, int fragmentIndex, Qgis::TextLayoutMode mode ) const;
|
||||||
|
%Docstring
|
||||||
|
Returns the vertical offset from a text block's baseline which should be applied
|
||||||
|
to the fragment at the specified index within that block.
|
||||||
|
|
||||||
.. versionadded:: 3.30
|
.. versionadded:: 3.30
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
@ -1460,7 +1460,7 @@ bool QgsPalLayerSettings::checkMinimumSizeMM( const QgsRenderContext &ct, const
|
|||||||
return QgsPalLabeling::checkMinimumSizeMM( ct, geom, minSize );
|
return QgsPalLabeling::checkMinimumSizeMM( ct, geom, minSize );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF *fm, const QString &text, double &labelX, double &labelY, const QgsFeature *f, QgsRenderContext *context, double *rotatedLabelX, double *rotatedLabelY, QgsTextDocument *document, QgsTextDocumentMetrics *documentMetrics )
|
void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF *fm, const QString &text, double &labelX, double &labelY, const QgsFeature *f, QgsRenderContext *context, double *rotatedLabelX, double *rotatedLabelY, QgsTextDocument *document, QgsTextDocumentMetrics *documentMetrics, QRectF *outerBounds )
|
||||||
{
|
{
|
||||||
if ( !fm || !f )
|
if ( !fm || !f )
|
||||||
{
|
{
|
||||||
@ -1714,6 +1714,16 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF *fm, const QSt
|
|||||||
*rotatedLabelY = rh * uPP;
|
*rotatedLabelY = rh * uPP;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if ( outerBounds && documentMetrics )
|
||||||
|
{
|
||||||
|
const QRectF outerBoundsPixels = documentMetrics->outerBounds( Qgis::TextLayoutMode::Labeling, orientation );
|
||||||
|
|
||||||
|
*outerBounds = QRectF( outerBoundsPixels.left() * uPP,
|
||||||
|
outerBoundsPixels.top() * uPP,
|
||||||
|
outerBoundsPixels.width() * uPP,
|
||||||
|
outerBoundsPixels.height() * uPP );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext &context )
|
void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext &context )
|
||||||
@ -2018,15 +2028,16 @@ std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerFeatureWithDetails
|
|||||||
|
|
||||||
QgsTextDocument doc;
|
QgsTextDocument doc;
|
||||||
QgsTextDocumentMetrics documentMetrics;
|
QgsTextDocumentMetrics documentMetrics;
|
||||||
|
QRectF outerBounds;
|
||||||
if ( format().allowHtmlFormatting() && !labelText.isEmpty() )
|
if ( format().allowHtmlFormatting() && !labelText.isEmpty() )
|
||||||
{
|
{
|
||||||
doc = QgsTextDocument::fromHtml( QStringList() << labelText );
|
doc = QgsTextDocument::fromHtml( QStringList() << labelText );
|
||||||
// also applies the line split to doc and calculates document metrics!
|
// also applies the line split to doc and calculates document metrics!
|
||||||
calculateLabelSize( labelFontMetrics.get(), labelText, labelWidth, labelHeight, mCurFeat, &context, &rotatedLabelX, &rotatedLabelY, &doc, &documentMetrics );
|
calculateLabelSize( labelFontMetrics.get(), labelText, labelWidth, labelHeight, mCurFeat, &context, &rotatedLabelX, &rotatedLabelY, &doc, &documentMetrics, &outerBounds );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
calculateLabelSize( labelFontMetrics.get(), labelText, labelWidth, labelHeight, mCurFeat, &context, &rotatedLabelX, &rotatedLabelY, nullptr, nullptr );
|
calculateLabelSize( labelFontMetrics.get(), labelText, labelWidth, labelHeight, mCurFeat, &context, &rotatedLabelX, &rotatedLabelY, nullptr, nullptr, &outerBounds );
|
||||||
}
|
}
|
||||||
|
|
||||||
// maximum angle between curved label characters (hardcoded defaults used in QGIS <2.0)
|
// maximum angle between curved label characters (hardcoded defaults used in QGIS <2.0)
|
||||||
@ -2668,6 +2679,11 @@ std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerFeatureWithDetails
|
|||||||
obstacleGeometry.boundingBox().height() ) );
|
obstacleGeometry.boundingBox().height() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( outerBounds.left() != 0 || outerBounds.top() != 0 || !qgsDoubleNear( outerBounds.width(), labelWidth ) || !qgsDoubleNear( outerBounds.height(), labelHeight ) )
|
||||||
|
{
|
||||||
|
labelFeature->setOuterBounds( outerBounds );
|
||||||
|
}
|
||||||
|
|
||||||
//set label's visual margin so that top visual margin is the leading, and bottom margin is the font's descent
|
//set label's visual margin so that top visual margin is the leading, and bottom margin is the font's descent
|
||||||
//this makes labels align to the font's baseline or highest character
|
//this makes labels align to the font's baseline or highest character
|
||||||
double topMargin = std::max( 0.25 * labelFontMetrics->ascent(), 0.0 );
|
double topMargin = std::max( 0.25 * labelFontMetrics->ascent(), 0.0 );
|
||||||
|
@ -758,7 +758,7 @@ class CORE_EXPORT QgsPalLayerSettings
|
|||||||
*/
|
*/
|
||||||
#ifndef SIP_RUN
|
#ifndef SIP_RUN
|
||||||
void calculateLabelSize( const QFontMetricsF *fm, const QString &text, double &labelX, double &labelY, const QgsFeature *f = nullptr, QgsRenderContext *context = nullptr, double *rotatedLabelX SIP_OUT = nullptr, double *rotatedLabelY SIP_OUT = nullptr,
|
void calculateLabelSize( const QFontMetricsF *fm, const QString &text, double &labelX, double &labelY, const QgsFeature *f = nullptr, QgsRenderContext *context = nullptr, double *rotatedLabelX SIP_OUT = nullptr, double *rotatedLabelY SIP_OUT = nullptr,
|
||||||
QgsTextDocument *document = nullptr, QgsTextDocumentMetrics *documentMetrics = nullptr );
|
QgsTextDocument *document = nullptr, QgsTextDocumentMetrics *documentMetrics = nullptr, QRectF *outerBounds = nullptr );
|
||||||
#else
|
#else
|
||||||
void calculateLabelSize( const QFontMetricsF *fm, const QString &text, double &labelX, double &labelY, const QgsFeature *f = nullptr, QgsRenderContext *context = nullptr, double *rotatedLabelX SIP_OUT = nullptr, double *rotatedLabelY SIP_OUT = nullptr );
|
void calculateLabelSize( const QFontMetricsF *fm, const QString &text, double &labelX, double &labelY, const QgsFeature *f = nullptr, QgsRenderContext *context = nullptr, double *rotatedLabelX SIP_OUT = nullptr, double *rotatedLabelY SIP_OUT = nullptr );
|
||||||
#endif
|
#endif
|
||||||
|
@ -556,7 +556,7 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition *label, Q
|
|||||||
painter->drawRect( rect );
|
painter->drawRect( rect );
|
||||||
|
|
||||||
|
|
||||||
painter->setPen( QColor( 0, 0, 0, 120 ) );
|
painter->setPen( QColor( 0, 0, 0, 60 ) );
|
||||||
const QgsMargins &margins = label->getFeaturePart()->feature()->visualMargin();
|
const QgsMargins &margins = label->getFeaturePart()->feature()->visualMargin();
|
||||||
if ( margins.top() > 0 )
|
if ( margins.top() > 0 )
|
||||||
{
|
{
|
||||||
@ -584,7 +584,10 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition *label, Q
|
|||||||
outerBoundsPt2.x() - outerBoundsPt1.x(),
|
outerBoundsPt2.x() - outerBoundsPt1.x(),
|
||||||
outerBoundsPt2.y() - outerBoundsPt1.y() );
|
outerBoundsPt2.y() - outerBoundsPt1.y() );
|
||||||
|
|
||||||
painter->setPen( QColor( 255, 0, 255, 140 ) );
|
QPen pen( QColor( 255, 0, 255, 140 ) );
|
||||||
|
pen.setCosmetic( true );
|
||||||
|
pen.setWidth( 1 );
|
||||||
|
painter->setPen( pen );
|
||||||
painter->drawRect( outerBoundsPixel );
|
painter->drawRect( outerBoundsPixel );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,13 +597,39 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition *label, Q
|
|||||||
const QgsTextDocument &document = textFeature->document();
|
const QgsTextDocument &document = textFeature->document();
|
||||||
const int blockCount = document.size();
|
const int blockCount = document.size();
|
||||||
|
|
||||||
|
double prevBlockBaseline = rect.bottom() - rect.top();
|
||||||
|
|
||||||
// draw block baselines
|
// draw block baselines
|
||||||
painter->setPen( QColor( 0, 0, 255, 220 ) );
|
|
||||||
for ( int blockIndex = 0; blockIndex < blockCount; ++blockIndex )
|
for ( int blockIndex = 0; blockIndex < blockCount; ++blockIndex )
|
||||||
{
|
{
|
||||||
const double blockBaseLine = metrics.baselineOffset( blockIndex, Qgis::TextLayoutMode::Labeling );
|
const double blockBaseLine = metrics.baselineOffset( blockIndex, Qgis::TextLayoutMode::Labeling );
|
||||||
painter->drawLine( QPointF( rect.left(), rect.top() + blockBaseLine ),
|
|
||||||
QPointF( rect.right(), rect.top() + blockBaseLine ) );
|
const QgsTextBlock &block = document.at( blockIndex );
|
||||||
|
const int fragmentCount = block.size();
|
||||||
|
double left = 0;
|
||||||
|
for ( int fragmentIndex = 0; fragmentIndex < fragmentCount; ++fragmentIndex )
|
||||||
|
{
|
||||||
|
const double fragmentVerticalOffset = metrics.fragmentVerticalOffset( blockIndex, fragmentIndex, Qgis::TextLayoutMode::Labeling );
|
||||||
|
const double right = left + metrics.fragmentHorizontalAdvance( blockIndex, fragmentIndex, Qgis::TextLayoutMode::Labeling );
|
||||||
|
|
||||||
|
if ( fragmentIndex > 0 )
|
||||||
|
{
|
||||||
|
QPen pen( QColor( 0, 0, 255, 220 ) );
|
||||||
|
pen.setStyle( Qt::PenStyle::DashLine );
|
||||||
|
|
||||||
|
painter->setPen( pen );
|
||||||
|
|
||||||
|
painter->drawLine( QPointF( rect.left() + left, rect.top() + blockBaseLine + fragmentVerticalOffset ),
|
||||||
|
QPointF( rect.left() + left, rect.top() + prevBlockBaseline ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
painter->setPen( QColor( 0, 0, 255, 220 ) );
|
||||||
|
painter->drawLine( QPointF( rect.left() + left, rect.top() + blockBaseLine + fragmentVerticalOffset ),
|
||||||
|
QPointF( rect.left() + right, rect.top() + blockBaseLine + fragmentVerticalOffset ) );
|
||||||
|
left = right;
|
||||||
|
}
|
||||||
|
prevBlockBaseline = blockBaseLine;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,13 @@
|
|||||||
|
|
||||||
#include <QFontMetricsF>
|
#include <QFontMetricsF>
|
||||||
|
|
||||||
|
// to match QTextEngine handling of superscript/subscript font sizes
|
||||||
|
constexpr double SUPERSCRIPT_SUBSCRIPT_FONT_SIZE_SCALING_FACTOR = 2.0 / 3.0;
|
||||||
|
|
||||||
|
// to match Qt behavior in QTextLine::draw
|
||||||
|
constexpr double SUPERSCRIPT_VERTICAL_BASELINE_ADJUSTMENT_FACTOR = 0.5;
|
||||||
|
constexpr double SUBSCRIPT_VERTICAL_BASELINE_ADJUSTMENT_FACTOR = 1.0 / 6.0;
|
||||||
|
|
||||||
QgsTextDocumentMetrics QgsTextDocumentMetrics::calculateMetrics( const QgsTextDocument &document, const QgsTextFormat &format, const QgsRenderContext &context, double scaleFactor )
|
QgsTextDocumentMetrics QgsTextDocumentMetrics::calculateMetrics( const QgsTextDocument &document, const QgsTextFormat &format, const QgsRenderContext &context, double scaleFactor )
|
||||||
{
|
{
|
||||||
QgsTextDocumentMetrics res;
|
QgsTextDocumentMetrics res;
|
||||||
@ -48,14 +55,25 @@ QgsTextDocumentMetrics QgsTextDocumentMetrics::calculateMetrics( const QgsTextDo
|
|||||||
|
|
||||||
QVector < double > blockVerticalLineSpacing;
|
QVector < double > blockVerticalLineSpacing;
|
||||||
|
|
||||||
|
double outerXMin = 0;
|
||||||
|
double outerXMax = 0;
|
||||||
|
double outerYMinLabel = 0;
|
||||||
|
double outerYMaxLabel = 0;
|
||||||
|
|
||||||
for ( int blockIndex = 0; blockIndex < blockSize; blockIndex++ )
|
for ( int blockIndex = 0; blockIndex < blockSize; blockIndex++ )
|
||||||
{
|
{
|
||||||
const QgsTextBlock &block = document.at( blockIndex );
|
const QgsTextBlock &block = document.at( blockIndex );
|
||||||
|
|
||||||
double blockWidth = 0;
|
double blockWidth = 0;
|
||||||
|
double blockXMax = 0;
|
||||||
|
double blockYMaxAdjustLabel = 0;
|
||||||
|
|
||||||
double blockHeightUsingAscentDescent = 0;
|
double blockHeightUsingAscentDescent = 0;
|
||||||
double blockHeightUsingLineSpacing = 0;
|
double blockHeightUsingLineSpacing = 0;
|
||||||
double blockHeightVerticalOrientation = 0;
|
double blockHeightVerticalOrientation = 0;
|
||||||
|
|
||||||
|
double blockHeightUsingAscentAccountingForVerticalOffset = 0;
|
||||||
|
|
||||||
const int fragmentSize = block.size();
|
const int fragmentSize = block.size();
|
||||||
|
|
||||||
double maxBlockAscent = 0;
|
double maxBlockAscent = 0;
|
||||||
@ -64,18 +82,89 @@ QgsTextDocumentMetrics QgsTextDocumentMetrics::calculateMetrics( const QgsTextDo
|
|||||||
double maxBlockLeading = 0;
|
double maxBlockLeading = 0;
|
||||||
double maxBlockMaxWidth = 0;
|
double maxBlockMaxWidth = 0;
|
||||||
|
|
||||||
|
QList< double > fragmentVerticalOffsets;
|
||||||
|
fragmentVerticalOffsets.reserve( fragmentSize );
|
||||||
|
|
||||||
QList< QFont > fragmentFonts;
|
QList< QFont > fragmentFonts;
|
||||||
fragmentFonts.reserve( fragmentSize );
|
fragmentFonts.reserve( fragmentSize );
|
||||||
QList< double >fragmentHorizontalAdvance;
|
QList< double >fragmentHorizontalAdvance;
|
||||||
fragmentHorizontalAdvance.reserve( fragmentSize );
|
fragmentHorizontalAdvance.reserve( fragmentSize );
|
||||||
|
|
||||||
|
QFont previousNonSuperSubScriptFont;
|
||||||
|
|
||||||
for ( int fragmentIndex = 0; fragmentIndex < fragmentSize; ++fragmentIndex )
|
for ( int fragmentIndex = 0; fragmentIndex < fragmentSize; ++fragmentIndex )
|
||||||
{
|
{
|
||||||
const QgsTextFragment &fragment = block.at( fragmentIndex );
|
const QgsTextFragment &fragment = block.at( fragmentIndex );
|
||||||
const QgsTextCharacterFormat &fragmentFormat = fragment.characterFormat();
|
const QgsTextCharacterFormat &fragmentFormat = fragment.characterFormat();
|
||||||
|
|
||||||
|
double fragmentHeightForVerticallyOffsetText = 0;
|
||||||
|
double fragmentYMaxAdjust = 0;
|
||||||
|
|
||||||
QFont updatedFont = font;
|
QFont updatedFont = font;
|
||||||
fragmentFormat.updateFontForFormat( updatedFont, context, scaleFactor );
|
fragmentFormat.updateFontForFormat( updatedFont, context, scaleFactor );
|
||||||
const QFontMetricsF fm( updatedFont );
|
|
||||||
|
QFontMetricsF fm( updatedFont );
|
||||||
|
|
||||||
|
if ( fragmentIndex == 0 )
|
||||||
|
previousNonSuperSubScriptFont = updatedFont;
|
||||||
|
|
||||||
|
double fragmentVerticalOffset = 0;
|
||||||
|
if ( fragmentFormat.hasVerticalAlignmentSet() )
|
||||||
|
{
|
||||||
|
switch ( fragmentFormat.verticalAlignment() )
|
||||||
|
{
|
||||||
|
case Qgis::TextCharacterVerticalAlignment::Normal:
|
||||||
|
previousNonSuperSubScriptFont = updatedFont;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qgis::TextCharacterVerticalAlignment::SuperScript:
|
||||||
|
{
|
||||||
|
const QFontMetricsF previousFM( previousNonSuperSubScriptFont );
|
||||||
|
|
||||||
|
if ( fragmentFormat.fontPointSize() < 0 )
|
||||||
|
{
|
||||||
|
// if fragment has no explicit font size set, then we scale the inherited font size to 60% of base font size
|
||||||
|
// this allows for easier use of super/subscript in labels as "my text<sup>2</sup>" will automatically render
|
||||||
|
// the superscript in a smaller font size. BUT if the fragment format HAS a non -1 font size then it indicates
|
||||||
|
// that the document has an explicit font size for the super/subscript element, eg "my text<sup style="font-size: 6pt">2</sup>"
|
||||||
|
// which we should respect
|
||||||
|
updatedFont.setPixelSize( updatedFont.pixelSize() * SUPERSCRIPT_SUBSCRIPT_FONT_SIZE_SCALING_FACTOR );
|
||||||
|
fm = QFontMetricsF( updatedFont );
|
||||||
|
}
|
||||||
|
|
||||||
|
// to match Qt behavior in QTextLine::draw
|
||||||
|
fragmentVerticalOffset = -( previousFM.ascent() + previousFM.descent() ) * SUPERSCRIPT_VERTICAL_BASELINE_ADJUSTMENT_FACTOR / scaleFactor;
|
||||||
|
|
||||||
|
// note -- this should really be fm.ascent(), not fm.capHeight() -- but in practice the ascent of most fonts is too large
|
||||||
|
// and causes unnecessarily large bounding boxes of vertically offset text!
|
||||||
|
fragmentHeightForVerticallyOffsetText = -fragmentVerticalOffset + fm.capHeight() / scaleFactor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Qgis::TextCharacterVerticalAlignment::SubScript:
|
||||||
|
{
|
||||||
|
const QFontMetricsF previousFM( previousNonSuperSubScriptFont );
|
||||||
|
|
||||||
|
if ( fragmentFormat.fontPointSize() < 0 )
|
||||||
|
{
|
||||||
|
// see above!!
|
||||||
|
updatedFont.setPixelSize( updatedFont.pixelSize() * SUPERSCRIPT_SUBSCRIPT_FONT_SIZE_SCALING_FACTOR );
|
||||||
|
fm = QFontMetricsF( updatedFont );
|
||||||
|
}
|
||||||
|
|
||||||
|
// to match Qt behavior in QTextLine::draw
|
||||||
|
fragmentVerticalOffset = ( previousFM.ascent() + previousFM.descent() ) * SUBSCRIPT_VERTICAL_BASELINE_ADJUSTMENT_FACTOR / scaleFactor;
|
||||||
|
|
||||||
|
fragmentYMaxAdjust = fragmentVerticalOffset + fm.descent() / scaleFactor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
previousNonSuperSubScriptFont = updatedFont;
|
||||||
|
}
|
||||||
|
fragmentVerticalOffsets << fragmentVerticalOffset;
|
||||||
|
|
||||||
const double fragmentWidth = fm.horizontalAdvance( fragment.text() ) / scaleFactor;
|
const double fragmentWidth = fm.horizontalAdvance( fragment.text() ) / scaleFactor;
|
||||||
|
|
||||||
@ -85,12 +174,19 @@ QgsTextDocumentMetrics QgsTextDocumentMetrics::calculateMetrics( const QgsTextDo
|
|||||||
const double fragmentHeightUsingLineSpacing = fm.lineSpacing() / scaleFactor;
|
const double fragmentHeightUsingLineSpacing = fm.lineSpacing() / scaleFactor;
|
||||||
|
|
||||||
blockWidth += fragmentWidth;
|
blockWidth += fragmentWidth;
|
||||||
|
blockXMax += fragmentWidth;
|
||||||
blockHeightUsingAscentDescent = std::max( blockHeightUsingAscentDescent, fragmentHeightUsingAscentDescent );
|
blockHeightUsingAscentDescent = std::max( blockHeightUsingAscentDescent, fragmentHeightUsingAscentDescent );
|
||||||
|
|
||||||
blockHeightUsingLineSpacing = std::max( blockHeightUsingLineSpacing, fragmentHeightUsingLineSpacing );
|
blockHeightUsingLineSpacing = std::max( blockHeightUsingLineSpacing, fragmentHeightUsingLineSpacing );
|
||||||
maxBlockAscent = std::max( maxBlockAscent, fm.ascent() / scaleFactor );
|
maxBlockAscent = std::max( maxBlockAscent, fm.ascent() / scaleFactor );
|
||||||
|
|
||||||
|
blockHeightUsingAscentAccountingForVerticalOffset = std::max( std::max( maxBlockAscent, fragmentHeightForVerticallyOffsetText ), blockHeightUsingAscentAccountingForVerticalOffset );
|
||||||
|
|
||||||
maxBlockDescent = std::max( maxBlockDescent, fm.descent() / scaleFactor );
|
maxBlockDescent = std::max( maxBlockDescent, fm.descent() / scaleFactor );
|
||||||
maxBlockMaxWidth = std::max( maxBlockMaxWidth, fm.maxWidth() / scaleFactor );
|
maxBlockMaxWidth = std::max( maxBlockMaxWidth, fm.maxWidth() / scaleFactor );
|
||||||
|
|
||||||
|
blockYMaxAdjustLabel = std::max( blockYMaxAdjustLabel, fragmentYMaxAdjust );
|
||||||
|
|
||||||
if ( ( fm.lineSpacing() / scaleFactor ) > maxLineSpacing )
|
if ( ( fm.lineSpacing() / scaleFactor ) > maxLineSpacing )
|
||||||
{
|
{
|
||||||
maxLineSpacing = fm.lineSpacing() / scaleFactor;
|
maxLineSpacing = fm.lineSpacing() / scaleFactor;
|
||||||
@ -117,6 +213,9 @@ QgsTextDocumentMetrics QgsTextDocumentMetrics::calculateMetrics( const QgsTextDo
|
|||||||
// for standard text rendering. Line height is also slightly different.
|
// for standard text rendering. Line height is also slightly different.
|
||||||
currentLabelBaseline = -res.mFirstLineAscentOffset;
|
currentLabelBaseline = -res.mFirstLineAscentOffset;
|
||||||
|
|
||||||
|
if ( blockHeightUsingAscentAccountingForVerticalOffset > maxBlockAscent )
|
||||||
|
outerYMinLabel = maxBlockAscent - blockHeightUsingAscentAccountingForVerticalOffset;
|
||||||
|
|
||||||
// standard rendering - designed to exactly replicate QPainter's drawText method
|
// standard rendering - designed to exactly replicate QPainter's drawText method
|
||||||
currentRectBaseline = -res.mFirstLineAscentOffset + lineHeight - 1 /*baseline*/;
|
currentRectBaseline = -res.mFirstLineAscentOffset + lineHeight - 1 /*baseline*/;
|
||||||
|
|
||||||
@ -141,11 +240,19 @@ QgsTextDocumentMetrics QgsTextDocumentMetrics::calculateMetrics( const QgsTextDo
|
|||||||
res.mLastLineAscentOffset = 0.25 * maxBlockAscent;
|
res.mLastLineAscentOffset = 0.25 * maxBlockAscent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( blockIndex == blockSize - 1 )
|
||||||
|
{
|
||||||
|
if ( blockYMaxAdjustLabel > maxBlockDescent )
|
||||||
|
outerYMaxLabel = blockYMaxAdjustLabel - maxBlockDescent;
|
||||||
|
}
|
||||||
|
|
||||||
blockVerticalLineSpacing << ( format.lineHeightUnit() == QgsUnitTypes::RenderPercentage ? ( maxBlockMaxWidth * format.lineHeight() ) : lineHeightPainterUnits );
|
blockVerticalLineSpacing << ( format.lineHeightUnit() == QgsUnitTypes::RenderPercentage ? ( maxBlockMaxWidth * format.lineHeight() ) : lineHeightPainterUnits );
|
||||||
|
|
||||||
res.mBlockHeights << blockHeightUsingLineSpacing;
|
res.mBlockHeights << blockHeightUsingLineSpacing;
|
||||||
|
|
||||||
width = std::max( width, blockWidth );
|
width = std::max( width, blockWidth );
|
||||||
|
outerXMax = std::max( outerXMax, blockXMax );
|
||||||
|
|
||||||
heightVerticalOrientation = std::max( heightVerticalOrientation, blockHeightVerticalOrientation );
|
heightVerticalOrientation = std::max( heightVerticalOrientation, blockHeightVerticalOrientation );
|
||||||
res.mBlockWidths << blockWidth;
|
res.mBlockWidths << blockWidth;
|
||||||
res.mFragmentFonts << fragmentFonts;
|
res.mFragmentFonts << fragmentFonts;
|
||||||
@ -154,6 +261,9 @@ QgsTextDocumentMetrics QgsTextDocumentMetrics::calculateMetrics( const QgsTextDo
|
|||||||
res.mBaselineOffsetsRectMode << currentRectBaseline;
|
res.mBaselineOffsetsRectMode << currentRectBaseline;
|
||||||
res.mBlockMaxDescent << maxBlockDescent;
|
res.mBlockMaxDescent << maxBlockDescent;
|
||||||
res.mBlockMaxCharacterWidth << maxBlockMaxWidth;
|
res.mBlockMaxCharacterWidth << maxBlockMaxWidth;
|
||||||
|
res.mFragmentVerticalOffsetsLabelMode << fragmentVerticalOffsets;
|
||||||
|
res.mFragmentVerticalOffsetsRectMode << fragmentVerticalOffsets;
|
||||||
|
res.mFragmentVerticalOffsetsPointMode << fragmentVerticalOffsets;
|
||||||
res.mFragmentHorizontalAdvance << fragmentHorizontalAdvance;
|
res.mFragmentHorizontalAdvance << fragmentHorizontalAdvance;
|
||||||
|
|
||||||
if ( blockIndex > 0 )
|
if ( blockIndex > 0 )
|
||||||
@ -169,6 +279,8 @@ QgsTextDocumentMetrics QgsTextDocumentMetrics::calculateMetrics( const QgsTextDo
|
|||||||
// adjust baselines
|
// adjust baselines
|
||||||
if ( !res.mBaselineOffsetsLabelMode.isEmpty() )
|
if ( !res.mBaselineOffsetsLabelMode.isEmpty() )
|
||||||
{
|
{
|
||||||
|
// outerYMinLabel += res.mBaselineOffsetsLabelMode[0];
|
||||||
|
|
||||||
const double labelModeBaselineAdjust = res.mBaselineOffsetsLabelMode.constLast() + res.mLastLineAscentOffset;
|
const double labelModeBaselineAdjust = res.mBaselineOffsetsLabelMode.constLast() + res.mLastLineAscentOffset;
|
||||||
const double pointModeBaselineAdjust = res.mBaselineOffsetsPointMode.constLast();
|
const double pointModeBaselineAdjust = res.mBaselineOffsetsPointMode.constLast();
|
||||||
for ( int i = 0; i < blockSize; ++i )
|
for ( int i = 0; i < blockSize; ++i )
|
||||||
@ -204,6 +316,10 @@ QgsTextDocumentMetrics QgsTextDocumentMetrics::calculateMetrics( const QgsTextDo
|
|||||||
res.mDocumentSizeVerticalOrientation = QSizeF( widthVerticalOrientation, heightVerticalOrientation );
|
res.mDocumentSizeVerticalOrientation = QSizeF( widthVerticalOrientation, heightVerticalOrientation );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res.mOuterBoundsLabelMode = QRectF( outerXMin, -outerYMaxLabel,
|
||||||
|
outerXMax - outerXMin,
|
||||||
|
heightLabelMode - outerYMinLabel + outerYMaxLabel );
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,6 +348,31 @@ QSizeF QgsTextDocumentMetrics::documentSize( Qgis::TextLayoutMode mode, Qgis::Te
|
|||||||
BUILTIN_UNREACHABLE
|
BUILTIN_UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRectF QgsTextDocumentMetrics::outerBounds( Qgis::TextLayoutMode mode, Qgis::TextOrientation orientation ) const
|
||||||
|
{
|
||||||
|
switch ( orientation )
|
||||||
|
{
|
||||||
|
case Qgis::TextOrientation::Horizontal:
|
||||||
|
switch ( mode )
|
||||||
|
{
|
||||||
|
case Qgis::TextLayoutMode::Rectangle:
|
||||||
|
case Qgis::TextLayoutMode::Point:
|
||||||
|
return QRectF();
|
||||||
|
|
||||||
|
case Qgis::TextLayoutMode::Labeling:
|
||||||
|
return mOuterBoundsLabelMode;
|
||||||
|
};
|
||||||
|
BUILTIN_UNREACHABLE
|
||||||
|
|
||||||
|
case Qgis::TextOrientation::Vertical:
|
||||||
|
return QRectF();
|
||||||
|
case Qgis::TextOrientation::RotationBased:
|
||||||
|
return QRectF(); // label mode only
|
||||||
|
}
|
||||||
|
|
||||||
|
BUILTIN_UNREACHABLE
|
||||||
|
}
|
||||||
|
|
||||||
double QgsTextDocumentMetrics::blockWidth( int blockIndex ) const
|
double QgsTextDocumentMetrics::blockWidth( int blockIndex ) const
|
||||||
{
|
{
|
||||||
return mBlockWidths.value( blockIndex );
|
return mBlockWidths.value( blockIndex );
|
||||||
@ -261,6 +402,20 @@ double QgsTextDocumentMetrics::fragmentHorizontalAdvance( int blockIndex, int fr
|
|||||||
return mFragmentHorizontalAdvance.value( blockIndex ).value( fragmentIndex );
|
return mFragmentHorizontalAdvance.value( blockIndex ).value( fragmentIndex );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double QgsTextDocumentMetrics::fragmentVerticalOffset( int blockIndex, int fragmentIndex, Qgis::TextLayoutMode mode ) const
|
||||||
|
{
|
||||||
|
switch ( mode )
|
||||||
|
{
|
||||||
|
case Qgis::TextLayoutMode::Rectangle:
|
||||||
|
return mFragmentVerticalOffsetsRectMode.value( blockIndex ).value( fragmentIndex );
|
||||||
|
case Qgis::TextLayoutMode::Point:
|
||||||
|
return mFragmentVerticalOffsetsPointMode.value( blockIndex ).value( fragmentIndex );
|
||||||
|
case Qgis::TextLayoutMode::Labeling:
|
||||||
|
return mFragmentVerticalOffsetsLabelMode.value( blockIndex ).value( fragmentIndex );
|
||||||
|
}
|
||||||
|
BUILTIN_UNREACHABLE
|
||||||
|
}
|
||||||
|
|
||||||
double QgsTextDocumentMetrics::verticalOrientationXOffset( int blockIndex ) const
|
double QgsTextDocumentMetrics::verticalOrientationXOffset( int blockIndex ) const
|
||||||
{
|
{
|
||||||
return mVerticalOrientationXOffsets.value( blockIndex );
|
return mVerticalOrientationXOffsets.value( blockIndex );
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QSizeF>
|
#include <QSizeF>
|
||||||
|
#include <QRectF>
|
||||||
|
|
||||||
class QgsTextDocument;
|
class QgsTextDocument;
|
||||||
class QgsRenderContext;
|
class QgsRenderContext;
|
||||||
@ -64,6 +65,17 @@ class CORE_EXPORT QgsTextDocumentMetrics
|
|||||||
*/
|
*/
|
||||||
QSizeF documentSize( Qgis::TextLayoutMode mode, Qgis::TextOrientation orientation ) const;
|
QSizeF documentSize( Qgis::TextLayoutMode mode, Qgis::TextOrientation orientation ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the outer bounds of the document, which is the documentSize() adjusted to account
|
||||||
|
* for any text elements which fall outside of the usual document margins (such as super or
|
||||||
|
* sub script elements)
|
||||||
|
*
|
||||||
|
* \warning Currently this is only supported for the Qgis::TextLayoutMode::Labeling mode.
|
||||||
|
*
|
||||||
|
* \since QGIS 3.30
|
||||||
|
*/
|
||||||
|
QRectF outerBounds( Qgis::TextLayoutMode mode, Qgis::TextOrientation orientation ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the width of the block at the specified index.
|
* Returns the width of the block at the specified index.
|
||||||
*/
|
*/
|
||||||
@ -86,6 +98,14 @@ class CORE_EXPORT QgsTextDocumentMetrics
|
|||||||
*/
|
*/
|
||||||
double fragmentHorizontalAdvance( int blockIndex, int fragmentIndex, Qgis::TextLayoutMode mode ) const;
|
double fragmentHorizontalAdvance( int blockIndex, int fragmentIndex, Qgis::TextLayoutMode mode ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the vertical offset from a text block's baseline which should be applied
|
||||||
|
* to the fragment at the specified index within that block.
|
||||||
|
*
|
||||||
|
* \since QGIS 3.30
|
||||||
|
*/
|
||||||
|
double fragmentVerticalOffset( int blockIndex, int fragmentIndex, Qgis::TextLayoutMode mode ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the vertical orientation x offset for the specified block.
|
* Returns the vertical orientation x offset for the specified block.
|
||||||
*/
|
*/
|
||||||
@ -119,6 +139,8 @@ class CORE_EXPORT QgsTextDocumentMetrics
|
|||||||
QSizeF mDocumentSizePointRectMode;
|
QSizeF mDocumentSizePointRectMode;
|
||||||
QSizeF mDocumentSizeVerticalOrientation;
|
QSizeF mDocumentSizeVerticalOrientation;
|
||||||
|
|
||||||
|
QRectF mOuterBoundsLabelMode;
|
||||||
|
|
||||||
QList < QList< QFont > > mFragmentFonts;
|
QList < QList< QFont > > mFragmentFonts;
|
||||||
QList< double > mBlockWidths;
|
QList< double > mBlockWidths;
|
||||||
QList< double > mBlockHeights;
|
QList< double > mBlockHeights;
|
||||||
@ -128,6 +150,10 @@ class CORE_EXPORT QgsTextDocumentMetrics
|
|||||||
|
|
||||||
QList< QList< double > > mFragmentHorizontalAdvance;
|
QList< QList< double > > mFragmentHorizontalAdvance;
|
||||||
|
|
||||||
|
QList< QList< double > > mFragmentVerticalOffsetsLabelMode;
|
||||||
|
QList< QList< double > > mFragmentVerticalOffsetsPointMode;
|
||||||
|
QList< QList< double > > mFragmentVerticalOffsetsRectMode;
|
||||||
|
|
||||||
QList< double > mVerticalOrientationXOffsets;
|
QList< double > mVerticalOrientationXOffsets;
|
||||||
QList< double > mBlockMaxDescent;
|
QList< double > mBlockMaxDescent;
|
||||||
QList< double > mBlockMaxCharacterWidth;
|
QList< double > mBlockMaxCharacterWidth;
|
||||||
|
@ -364,7 +364,8 @@ double QgsTextRenderer::drawBuffer( QgsRenderContext &context, const QgsTextRend
|
|||||||
if ( component.extraWordSpacing || component.extraLetterSpacing )
|
if ( component.extraWordSpacing || component.extraLetterSpacing )
|
||||||
applyExtraSpacingForLineJustification( fragmentFont, component.extraWordSpacing, component.extraLetterSpacing );
|
applyExtraSpacingForLineJustification( fragmentFont, component.extraWordSpacing, component.extraLetterSpacing );
|
||||||
|
|
||||||
path.addText( xOffset, 0, fragmentFont, fragment.text() );
|
const double yOffset = metrics.fragmentVerticalOffset( component.blockIndex, fragmentIndex, mode );
|
||||||
|
path.addText( xOffset, yOffset, fragmentFont, fragment.text() );
|
||||||
|
|
||||||
xOffset += metrics.fragmentHorizontalAdvance( component.blockIndex, fragmentIndex, mode );
|
xOffset += metrics.fragmentHorizontalAdvance( component.blockIndex, fragmentIndex, mode );
|
||||||
|
|
||||||
@ -390,12 +391,15 @@ double QgsTextRenderer::drawBuffer( QgsRenderContext &context, const QgsTextRend
|
|||||||
|
|
||||||
const QFontMetricsF fragmentMetrics( fragmentFont );
|
const QFontMetricsF fragmentMetrics( fragmentFont );
|
||||||
|
|
||||||
|
const double fragmentYOffset = metrics.fragmentVerticalOffset( component.blockIndex, fragmentIndex, mode )
|
||||||
|
/ 1;
|
||||||
|
|
||||||
const QStringList parts = QgsPalLabeling::splitToGraphemes( fragment.text() );
|
const QStringList parts = QgsPalLabeling::splitToGraphemes( fragment.text() );
|
||||||
for ( const QString &part : parts )
|
for ( const QString &part : parts )
|
||||||
{
|
{
|
||||||
double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / scaleFactor - letterSpacing ) ) / 2;
|
double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / scaleFactor - letterSpacing ) ) / 2;
|
||||||
partYOffset += fragmentMetrics.ascent() / scaleFactor;
|
partYOffset += fragmentMetrics.ascent() / scaleFactor;
|
||||||
path.addText( partXOffset, partYOffset, fragmentFont, part );
|
path.addText( partXOffset, partYOffset + fragmentYOffset, fragmentFont, part );
|
||||||
partYOffset += letterSpacing;
|
partYOffset += letterSpacing;
|
||||||
}
|
}
|
||||||
partLastDescent = fragmentMetrics.descent() / scaleFactor;
|
partLastDescent = fragmentMetrics.descent() / scaleFactor;
|
||||||
@ -525,7 +529,8 @@ void QgsTextRenderer::drawMask( QgsRenderContext &context, const QgsTextRenderer
|
|||||||
{
|
{
|
||||||
const QFont fragmentFont = metrics.fragmentFont( component.blockIndex, fragmentIndex );
|
const QFont fragmentFont = metrics.fragmentFont( component.blockIndex, fragmentIndex );
|
||||||
|
|
||||||
path.addText( xOffset, 0, fragmentFont, fragment.text() );
|
const double fragmentYOffset = metrics.fragmentVerticalOffset( component.blockIndex, fragmentIndex, mode );
|
||||||
|
path.addText( xOffset, fragmentYOffset, fragmentFont, fragment.text() );
|
||||||
|
|
||||||
xOffset += metrics.fragmentHorizontalAdvance( component.blockIndex, fragmentIndex, mode );
|
xOffset += metrics.fragmentHorizontalAdvance( component.blockIndex, fragmentIndex, mode );
|
||||||
fragmentIndex++;
|
fragmentIndex++;
|
||||||
@ -1621,7 +1626,9 @@ void QgsTextRenderer::drawTextInternalHorizontal( QgsRenderContext &context, con
|
|||||||
if ( extraWordSpace || extraLetterSpace )
|
if ( extraWordSpace || extraLetterSpace )
|
||||||
applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
|
applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
|
||||||
|
|
||||||
path.addText( xOffset, 0, fragmentFont, fragment.text() );
|
const double yOffset = metrics.fragmentVerticalOffset( blockIndex, fragmentIndex, mode );
|
||||||
|
|
||||||
|
path.addText( xOffset, yOffset, fragmentFont, fragment.text() );
|
||||||
|
|
||||||
QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.color();
|
QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.color();
|
||||||
textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.opacity() : format.opacity() );
|
textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.opacity() : format.opacity() );
|
||||||
@ -1673,6 +1680,8 @@ void QgsTextRenderer::drawTextInternalHorizontal( QgsRenderContext &context, con
|
|||||||
if ( extraWordSpace || extraLetterSpace )
|
if ( extraWordSpace || extraLetterSpace )
|
||||||
applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
|
applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
|
||||||
|
|
||||||
|
const double yOffset = metrics.fragmentVerticalOffset( blockIndex, fragmentIndex, mode );
|
||||||
|
|
||||||
QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.color();
|
QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.color();
|
||||||
textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.opacity() : format.opacity() );
|
textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.opacity() : format.opacity() );
|
||||||
|
|
||||||
@ -1681,7 +1690,7 @@ void QgsTextRenderer::drawTextInternalHorizontal( QgsRenderContext &context, con
|
|||||||
context.painter()->setRenderHint( QPainter::TextAntialiasing );
|
context.painter()->setRenderHint( QPainter::TextAntialiasing );
|
||||||
|
|
||||||
context.painter()->scale( 1 / fontScale, 1 / fontScale );
|
context.painter()->scale( 1 / fontScale, 1 / fontScale );
|
||||||
context.painter()->drawText( xOffset, 0, fragment.text() );
|
context.painter()->drawText( xOffset, yOffset, fragment.text() );
|
||||||
context.painter()->scale( fontScale, fontScale );
|
context.painter()->scale( fontScale, fontScale );
|
||||||
|
|
||||||
xOffset += metrics.fragmentHorizontalAdvance( blockIndex, fragmentIndex, mode );
|
xOffset += metrics.fragmentHorizontalAdvance( blockIndex, fragmentIndex, mode );
|
||||||
|
@ -3310,6 +3310,75 @@ class PyQgsTextRenderer(unittest.TestCase):
|
|||||||
'<i>t</i><b style="font-size: 30pt">e</b><p><span style="color: red">s<span style="color: rgba(255,0,0,0.5); text-decoration: underline; font-size:80pt">t</span></span>'],
|
'<i>t</i><b style="font-size: 30pt">e</b><p><span style="color: red">s<span style="color: rgba(255,0,0,0.5); text-decoration: underline; font-size:80pt">t</span></span>'],
|
||||||
point=QPointF(50, 200))
|
point=QPointF(50, 200))
|
||||||
|
|
||||||
|
def testHtmlSuperSubscript(self):
|
||||||
|
format = QgsTextFormat()
|
||||||
|
format.setFont(getTestFont('bold'))
|
||||||
|
format.setSize(60)
|
||||||
|
format.setSizeUnit(QgsUnitTypes.RenderPoints)
|
||||||
|
format.setColor(QColor(255, 0, 0))
|
||||||
|
format.setAllowHtmlFormatting(True)
|
||||||
|
assert self.checkRenderPoint(format, 'text_html_supersubscript', None, text=[
|
||||||
|
'<sub>sub</sub>N<sup>sup</sup>'],
|
||||||
|
point=QPointF(50, 200))
|
||||||
|
|
||||||
|
def testHtmlSuperSubscriptFixedFontSize(self):
|
||||||
|
format = QgsTextFormat()
|
||||||
|
format.setFont(getTestFont('bold'))
|
||||||
|
format.setSize(60)
|
||||||
|
format.setSizeUnit(QgsUnitTypes.RenderPoints)
|
||||||
|
format.setColor(QColor(255, 0, 0))
|
||||||
|
format.setAllowHtmlFormatting(True)
|
||||||
|
assert self.checkRenderPoint(format, 'text_html_supersubscript_fixed_font_size', None, text=[
|
||||||
|
'<sub style="font-size:80pt">s<span style="font-size:30pt">u</span></sub>N<sup style="font-size:40pt">s<span style="font-size: 20pt">up</span></sup>'],
|
||||||
|
point=QPointF(50, 200))
|
||||||
|
|
||||||
|
def testHtmlSuperSubscriptBuffer(self):
|
||||||
|
format = QgsTextFormat()
|
||||||
|
format.setFont(getTestFont('bold'))
|
||||||
|
format.setSize(60)
|
||||||
|
format.setSizeUnit(QgsUnitTypes.RenderPoints)
|
||||||
|
format.setColor(QColor(255, 0, 0))
|
||||||
|
format.setAllowHtmlFormatting(True)
|
||||||
|
format.buffer().setEnabled(True)
|
||||||
|
format.buffer().setSize(5)
|
||||||
|
format.buffer().setColor(QColor(50, 150, 200))
|
||||||
|
assert self.checkRenderPoint(format, 'text_html_supersubscript_buffer', None, text=[
|
||||||
|
'<sub>sub</sub>N<sup>sup</sup>'],
|
||||||
|
point=QPointF(50, 200))
|
||||||
|
|
||||||
|
def testHtmlSuperSubscriptShadow(self):
|
||||||
|
format = QgsTextFormat()
|
||||||
|
format.setFont(getTestFont('bold'))
|
||||||
|
format.setSize(60)
|
||||||
|
format.setSizeUnit(QgsUnitTypes.RenderPoints)
|
||||||
|
format.setColor(QColor(0, 255, 0))
|
||||||
|
format.setAllowHtmlFormatting(True)
|
||||||
|
format.shadow().setEnabled(True)
|
||||||
|
format.shadow().setOffsetDistance(5)
|
||||||
|
format.shadow().setBlurRadius(0)
|
||||||
|
format.shadow().setColor(QColor(50, 150, 200))
|
||||||
|
assert self.checkRenderPoint(format, 'text_html_supersubscript_shadow', None, text=[
|
||||||
|
'<sub>sub</sub>N<sup>sup</sup>'],
|
||||||
|
point=QPointF(50, 200))
|
||||||
|
|
||||||
|
def testHtmlSuperSubscriptBufferShadow(self):
|
||||||
|
format = QgsTextFormat()
|
||||||
|
format.setFont(getTestFont('bold'))
|
||||||
|
format.setSize(60)
|
||||||
|
format.setSizeUnit(QgsUnitTypes.RenderPoints)
|
||||||
|
format.setColor(QColor(0, 255, 0))
|
||||||
|
format.setAllowHtmlFormatting(True)
|
||||||
|
format.buffer().setEnabled(True)
|
||||||
|
format.buffer().setSize(5)
|
||||||
|
format.buffer().setColor(QColor(200, 50, 150))
|
||||||
|
format.shadow().setEnabled(True)
|
||||||
|
format.shadow().setOffsetDistance(5)
|
||||||
|
format.shadow().setBlurRadius(0)
|
||||||
|
format.shadow().setColor(QColor(50, 150, 200))
|
||||||
|
assert self.checkRenderPoint(format, 'text_html_supersubscript_buffer_shadow', None, text=[
|
||||||
|
'<sub>sub</sub>N<sup>sup</sup>'],
|
||||||
|
point=QPointF(50, 200))
|
||||||
|
|
||||||
def testTextRenderFormat(self):
|
def testTextRenderFormat(self):
|
||||||
format = QgsTextFormat()
|
format = QgsTextFormat()
|
||||||
format.setFont(getTestFont('bold'))
|
format.setFont(getTestFont('bold'))
|
||||||
|
BIN
tests/testdata/control_images/text_renderer/text_html_supersubscript/text_html_supersubscript.png
vendored
Normal file
BIN
tests/testdata/control_images/text_renderer/text_html_supersubscript/text_html_supersubscript.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
Loading…
x
Reference in New Issue
Block a user