Skip to content
Permalink
Browse files

General cleanups, and add support for underline/overline/strikethroug…

…h formatting tags
  • Loading branch information
nyalldawson committed May 11, 2020
1 parent 173e209 commit fe14e52e167ca22fdf7687c5948018dc496ff96e
Showing with 315 additions and 72 deletions.
  1. +12 −8 python/core/auto_generated/qgstextrenderer.sip.in
  2. +147 −15 src/core/qgstextrenderer.cpp
  3. +156 −49 src/core/qgstextrenderer.h
@@ -1998,9 +1998,9 @@ Draws text at a point origin using the specified settings.
as of QGIS 3.4.3 and the text format should be set using QgsRenderContext.setTextRenderFormat() instead.
%End

static void drawPart( const QRectF &rect, double rotation, HAlignment alignment, const QStringList &textLines,
QgsRenderContext &context, const QgsTextFormat &format,
TextPart part, bool drawAsOutlines = true );
static void drawPart( const QRectF &rect, double rotation, HAlignment alignment, const QStringList &textLines,
QgsRenderContext &context, const QgsTextFormat &format,
TextPart part, bool drawAsOutlines = true ) /Deprecated/;
%Docstring
Draws a single component of rendered text using the specified settings.

@@ -2017,12 +2017,14 @@ Draws a single component of rendered text using the specified settings.
formats like SVG to maintain text as text objects, but at the cost of degraded
rendering and may result in side effects like misaligned text buffers. This setting is deprecated and has no effect
as of QGIS 3.4.3 and the text format should be set using QgsRenderContext.setTextRenderFormat() instead.
%End

.. deprecated::
Private API only, will be removed in 4.0
%End

static void drawPart( QPointF origin, double rotation, HAlignment alignment, const QStringList &textLines,
QgsRenderContext &context, const QgsTextFormat &format,
TextPart part, bool drawAsOutlines = true );
static void drawPart( QPointF origin, double rotation, HAlignment alignment, const QStringList &textLines,
QgsRenderContext &context, const QgsTextFormat &format,
TextPart part, bool drawAsOutlines = true ) /Deprecated/;
%Docstring
Draws a single component of rendered text using the specified settings.

@@ -2039,8 +2041,10 @@ Draws a single component of rendered text using the specified settings.
formats like SVG to maintain text as text objects, but at the cost of degraded
rendering and may result in side effects like misaligned text buffers. This setting is deprecated and has no effect
as of QGIS 3.4.3 and the text format should be set using QgsRenderContext.setTextRenderFormat() instead.
%End

.. deprecated::
Private API only, will be removed in 4.0
%End

static QFontMetricsF fontMetrics( QgsRenderContext &context, const QgsTextFormat &format );
%Docstring
@@ -2649,17 +2649,19 @@ void QgsTextRenderer::drawText( const QRectF &rect, double rotation, QgsTextRend
tmpFormat.updateDataDefinedProperties( context );
tmpFormat = updateShadowPosition( tmpFormat );

const QgsTextDocument document = format.allowHtmlFormatting() ? QgsTextDocument::fromHtml( textLines ) : QgsTextDocument::fromPlainText( textLines );

if ( tmpFormat.background().enabled() )
{
drawPart( rect, rotation, alignment, textLines, context, tmpFormat, Background );
drawPart( rect, rotation, alignment, document, context, tmpFormat, Background );
}

if ( tmpFormat.buffer().enabled() )
{
drawPart( rect, rotation, alignment, textLines, context, tmpFormat, Buffer );
drawPart( rect, rotation, alignment, document, context, tmpFormat, Buffer );
}

drawPart( rect, rotation, alignment, textLines, context, tmpFormat, Text );
drawPart( rect, rotation, alignment, document, context, tmpFormat, Text );
}

void QgsTextRenderer::drawText( QPointF point, double rotation, QgsTextRenderer::HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool )
@@ -2669,17 +2671,19 @@ void QgsTextRenderer::drawText( QPointF point, double rotation, QgsTextRenderer:
tmpFormat.updateDataDefinedProperties( context );
tmpFormat = updateShadowPosition( tmpFormat );

const QgsTextDocument document = format.allowHtmlFormatting() ? QgsTextDocument::fromHtml( textLines ) : QgsTextDocument::fromPlainText( textLines );

if ( tmpFormat.background().enabled() )
{
drawPart( point, rotation, alignment, textLines, context, tmpFormat, Background );
drawPart( point, rotation, alignment, document, context, tmpFormat, Background );
}

if ( tmpFormat.buffer().enabled() )
{
drawPart( point, rotation, alignment, textLines, context, tmpFormat, Buffer );
drawPart( point, rotation, alignment, document, context, tmpFormat, Buffer );
}

drawPart( point, rotation, alignment, textLines, context, tmpFormat, Text );
drawPart( point, rotation, alignment, document, context, tmpFormat, Text );
}

QgsTextFormat QgsTextRenderer::updateShadowPosition( const QgsTextFormat &format )
@@ -2706,7 +2710,9 @@ QgsTextFormat QgsTextRenderer::updateShadowPosition( const QgsTextFormat &format
void QgsTextRenderer::drawPart( const QRectF &rect, double rotation, HAlignment alignment,
const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, QgsTextRenderer::TextPart part, bool )
{
drawPart( rect, rotation, alignment, QgsTextDocument( textLines ), context, format, part );
const QgsTextDocument document = format.allowHtmlFormatting() ? QgsTextDocument::fromHtml( textLines ) : QgsTextDocument::fromPlainText( textLines );

drawPart( rect, rotation, alignment, document, context, format, part );
}

void QgsTextRenderer::drawPart( const QRectF &rect, double rotation, QgsTextRenderer::HAlignment alignment, const QgsTextDocument &document, QgsRenderContext &context, const QgsTextFormat &format, QgsTextRenderer::TextPart part )
@@ -2775,7 +2781,8 @@ void QgsTextRenderer::drawPart( const QRectF &rect, double rotation, QgsTextRend

void QgsTextRenderer::drawPart( QPointF origin, double rotation, QgsTextRenderer::HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, QgsTextRenderer::TextPart part, bool )
{
drawPart( origin, rotation, alignment, QgsTextDocument( textLines ), context, format, part );
const QgsTextDocument document = format.allowHtmlFormatting() ? QgsTextDocument::fromHtml( textLines ) : QgsTextDocument::fromPlainText( textLines );
drawPart( origin, rotation, alignment, document, context, format, part );
}

void QgsTextRenderer::drawPart( QPointF origin, double rotation, QgsTextRenderer::HAlignment alignment, const QgsTextDocument &document, QgsRenderContext &context, const QgsTextFormat &format, QgsTextRenderer::TextPart part )
@@ -3795,25 +3802,30 @@ void QgsTextRenderer::drawTextInternal( TextPart drawType,
QPainter textp;
textp.begin( &textPict );
textp.setPen( Qt::NoPen );
QFont font = format.scaledFont( context );
const QFont font = format.scaledFont( context );

double xOffset = 0;
for ( const QgsTextFragment &fragment : block )
{
// draw text, QPainterPath method
QPainterPath path;
path.setFillRule( Qt::WindingFill );
path.addText( xOffset, 0, font, fragment.text() );

QFont fragmentFont = font;
fragment.characterFormat().updateFontForFormat( fragmentFont );
QFontMetricsF fragmentMetrics = QFontMetricsF( fragmentFont );

path.addText( xOffset, 0, fragmentFont, fragment.text() );

QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.color();
textColor.setAlphaF( format.opacity() );
textp.setBrush( textColor );
textp.drawPath( path );

#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
xOffset += fontMetrics->width( fragment.text() );
xOffset += fragmentMetrics.width( fragment.text() );
#else
xOffset += fontMetrics->horizontalAdvance( fragment.text() );
xOffset += fragmentMetrics.horizontalAdvance( fragment.text() );
#endif
// TODO: why are some font settings lost on drawPicture() when using drawText() inside QPicture?
// e.g. some capitalization options, but not others
@@ -4201,6 +4213,13 @@ QgsTextFormat::TextOrientation QgsTextRendererUtils::decodeTextOrientation( cons

QgsTextCharacterFormat::QgsTextCharacterFormat( const QTextCharFormat &format )
: mTextColor( format.hasProperty( QTextFormat::ForegroundBrush ) ? format.foreground().color() : QColor() )
#if 0 // settings which affect font metrics are disabled for now
, mFontWeight( format.hasProperty( QTextFormat::FontWeight ) ? format.fontWeight() : -1 )
, mItalic( format.hasProperty( QTextFormat::FontItalic ) ? ( format.fontItalic() ? BooleanValue::True : BooleanValue::False ) : BooleanValue::NotSet )
#endif
, mStrikethrough( format.hasProperty( QTextFormat::FontStrikeOut ) ? ( format.fontStrikeOut() ? BooleanValue::True : BooleanValue::False ) : BooleanValue::NotSet )
, mUnderline( format.hasProperty( QTextFormat::FontUnderline ) ? ( format.fontUnderline() ? BooleanValue::True : BooleanValue::False ) : BooleanValue::NotSet )
, mOverline( format.hasProperty( QTextFormat::FontOverline ) ? ( format.fontOverline() ? BooleanValue::True : BooleanValue::False ) : BooleanValue::NotSet )
{

}
@@ -4215,6 +4234,75 @@ void QgsTextCharacterFormat::setTextColor( const QColor &textColor )
mTextColor = textColor;
}

QgsTextCharacterFormat::BooleanValue QgsTextCharacterFormat::strikeOut() const
{
return mStrikethrough;
}

void QgsTextCharacterFormat::setStrikeOut( BooleanValue strikethrough )
{
mStrikethrough = strikethrough;
}

QgsTextCharacterFormat::BooleanValue QgsTextCharacterFormat::underline() const
{
return mUnderline;
}

void QgsTextCharacterFormat::setUnderline( BooleanValue underline )
{
mUnderline = underline;
}

QgsTextCharacterFormat::BooleanValue QgsTextCharacterFormat::overline() const
{
return mOverline;
}

void QgsTextCharacterFormat::setOverline( QgsTextCharacterFormat::BooleanValue enabled )
{
mOverline = enabled;
}

void QgsTextCharacterFormat::updateFontForFormat( QFont &font ) const
{
if ( mUnderline != BooleanValue::NotSet )
font.setUnderline( mUnderline == QgsTextCharacterFormat::BooleanValue::True );
if ( mOverline != BooleanValue::NotSet )
font.setOverline( mOverline == QgsTextCharacterFormat::BooleanValue::True );
if ( mStrikethrough != QgsTextCharacterFormat::BooleanValue::NotSet )
font.setStrikeOut( mStrikethrough == QgsTextCharacterFormat::BooleanValue::True );

#if 0 // settings which affect font metrics are disabled for now
if ( mItalic != QgsTextCharacterFormat::BooleanValue::NotSet )
font.setItalic( mItalic == QgsTextCharacterFormat::BooleanValue::True );
if ( mFontWeight != -1 )
font.setWeight( mFontWeight );
#endif
}

#if 0 // settings which affect font metrics are disabled for now
QgsTextCharacterFormat::BooleanValue QgsTextCharacterFormat::italic() const
{
return mItalic;
}

void QgsTextCharacterFormat::setItalic( QgsTextCharacterFormat::BooleanValue enabled )
{
mItalic = enabled;
}

int QgsTextCharacterFormat::fontWeight() const
{
return mFontWeight;
}

void QgsTextCharacterFormat::setFontWeight( int fontWeight )
{
mFontWeight = fontWeight;
}
#endif

//
// QgsTextFragment
//
@@ -4223,6 +4311,13 @@ QgsTextFragment::QgsTextFragment( const QString &text, const QgsTextCharacterFor
, mCharFormat( format )
{}

QgsTextFragment::QgsTextFragment( const QTextFragment &fragment )
: mText( fragment.text() )
, mCharFormat( QgsTextCharacterFormat( fragment.charFormat() ) )
{

}

QString QgsTextFragment::text() const
{
return mText;
@@ -4259,11 +4354,48 @@ QgsTextDocument::QgsTextDocument( const QgsTextFragment &fragment )
append( QgsTextBlock( fragment ) );
}

QgsTextDocument::QgsTextDocument( const QStringList &lines )
QgsTextDocument QgsTextDocument::fromPlainText( const QStringList &lines )
{
reserve( lines.size() );
QgsTextDocument document;
document.reserve( lines.size() );
for ( const QString &line : lines )
append( QgsTextBlock( QgsTextFragment( line ) ) );
document.append( QgsTextBlock( QgsTextFragment( line ) ) );
return document;
}

QgsTextDocument QgsTextDocument::fromHtml( const QStringList &lines )
{
QgsTextDocument document;

document.reserve( lines.size() );
for ( const QString &line : lines )
{
QTextDocument sourceDoc;
sourceDoc.setHtml( line );

QTextBlock sourceBlock = sourceDoc.firstBlock();
while ( true )
{
auto it = sourceBlock.begin();
QgsTextBlock block;
while ( !it.atEnd() )
{
const QTextFragment fragment = it.fragment();
if ( fragment.isValid() )
{
block.append( QgsTextFragment( fragment ) );
}
it++;
}
if ( !block.isEmpty() )
document << block;

sourceBlock = sourceBlock.next();
if ( !sourceBlock.isValid() )
break;
}
}
return document;
}

QStringList QgsTextDocument::toPlainText() const

0 comments on commit fe14e52

Please sign in to comment.
You can’t perform that action at this time.