Navigation Menu

Skip to content

Commit

Permalink
General cleanups, and add support for underline/overline/strikethroug…
Browse files Browse the repository at this point in the history
…h formatting tags
  • Loading branch information
nyalldawson committed May 12, 2020
1 parent 173e209 commit fe14e52
Show file tree
Hide file tree
Showing 3 changed files with 315 additions and 72 deletions.
20 changes: 12 additions & 8 deletions python/core/auto_generated/qgstextrenderer.sip.in
Expand Up @@ -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.

Expand All @@ -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.

Expand All @@ -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
Expand Down
162 changes: 147 additions & 15 deletions src/core/qgstextrenderer.cpp
Expand Up @@ -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 )
Expand All @@ -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 )
Expand All @@ -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 )
Expand Down Expand Up @@ -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 )
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 )
{

}
Expand All @@ -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
//
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit fe14e52

Please sign in to comment.