Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[api] Move setting to control how text is rendered to QgsRenderContext
The new QgsRenderContext::TextRenderFormat enum controls how text
should be handled during a render operation, e.g. whether to render
text as outlines (paths) or keep it as real text objects.

Deprecate previous arguments in QgsTextRenderer which handled
this same use case.

This allows us to make the setting vary per-render, instead of
having a single global flag controlling the setting. Ultimately
this will allow us to have different behaviour within the
canvas renders vs print layout exports.

Refs #3975

(cherry picked from commit 53345c3)
  • Loading branch information
nyalldawson committed Dec 11, 2018
1 parent 4631a0b commit 7c5a74d
Show file tree
Hide file tree
Showing 12 changed files with 289 additions and 41 deletions.
19 changes: 19 additions & 0 deletions python/core/auto_generated/qgsmapsettings.sip.in
Expand Up @@ -281,6 +281,24 @@ Returns combination of flags used for rendering
bool testFlag( Flag flag ) const;
%Docstring
Check whether a particular flag is enabled
%End

QgsRenderContext::TextRenderFormat textRenderFormat() const;
%Docstring
Returns the text render format, which dictates how text is rendered (e.g. as paths or real text objects).

.. seealso:: :py:func:`setTextRenderFormat`

.. versionadded:: 3.4.3
%End

void setTextRenderFormat( QgsRenderContext::TextRenderFormat format );
%Docstring
Sets the text render ``format``, which dictates how text is rendered (e.g. as paths or real text objects).

.. seealso:: :py:func:`textRenderFormat`

.. versionadded:: 3.4.3
%End

void setOutputImageFormat( QImage::Format format );
Expand Down Expand Up @@ -516,6 +534,7 @@ Returns global configuration of the labeling engine




void updateDerived();
};

Expand Down
24 changes: 24 additions & 0 deletions python/core/auto_generated/qgsrendercontext.sip.in
Expand Up @@ -45,6 +45,12 @@ to be rendered etc.
typedef QFlags<QgsRenderContext::Flag> Flags;


enum TextRenderFormat
{
TextFormatAlwaysOutlines,
TextFormatAlwaysText,
};

void setFlags( QgsRenderContext::Flags flags );
%Docstring
Set combination of flags that will be used for rendering.
Expand Down Expand Up @@ -392,6 +398,24 @@ Convert meter distances to active MapUnit values for QgsUnitTypes.RenderMetersIn
When the sourceCrs() is geographic, the center of the Extent will be used

.. versionadded:: 3.0
%End

TextRenderFormat textRenderFormat() const;
%Docstring
Returns the text render format, which dictates how text is rendered (e.g. as paths or real text objects).

.. seealso:: :py:func:`setTextRenderFormat`

.. versionadded:: 3.4.3
%End

void setTextRenderFormat( TextRenderFormat format );
%Docstring
Sets the text render ``format``, which dictates how text is rendered (e.g. as paths or real text objects).

.. seealso:: :py:func:`textRenderFormat`

.. versionadded:: 3.4.3
%End

};
Expand Down
13 changes: 9 additions & 4 deletions python/core/auto_generated/qgstextrenderer.sip.in
Expand Up @@ -1555,6 +1555,7 @@ Calculates pixel size (considering output size should be in pixel or map units,
:return: font pixel size
%End


static void drawText( const QRectF &rect, double rotation, HAlignment alignment, const QStringList &textLines,
QgsRenderContext &context, const QgsTextFormat &format,
bool drawAsOutlines = true );
Expand All @@ -1569,7 +1570,8 @@ Draws text within a rectangle using the specified settings.
:param format: text format
:param drawAsOutlines: set to false to render text as text. This allows outputs to
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.
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

static void drawText( QPointF point, double rotation, HAlignment alignment, const QStringList &textLines,
Expand All @@ -1586,7 +1588,8 @@ Draws text at a point origin using the specified settings.
:param format: text format
:param drawAsOutlines: set to false to render text as text. This allows outputs to
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.
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

static void drawPart( const QRectF &rect, double rotation, HAlignment alignment, const QStringList &textLines,
Expand All @@ -1606,7 +1609,8 @@ Draws a single component of rendered text using the specified settings.
with the text or background parts)
:param drawAsOutlines: set to false to render text as text. This allows outputs to
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.
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

static void drawPart( QPointF origin, double rotation, HAlignment alignment, const QStringList &textLines,
Expand All @@ -1626,7 +1630,8 @@ Draws a single component of rendered text using the specified settings.
with the text or background parts)
:param drawAsOutlines: set to false to render text as text. This allows outputs to
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.
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

static QFontMetricsF fontMetrics( QgsRenderContext &context, const QgsTextFormat &format );
Expand Down
24 changes: 24 additions & 0 deletions src/core/qgsmapsettings.h
Expand Up @@ -253,6 +253,28 @@ class CORE_EXPORT QgsMapSettings
//! Check whether a particular flag is enabled
bool testFlag( Flag flag ) const;

/**
* Returns the text render format, which dictates how text is rendered (e.g. as paths or real text objects).
*
* \see setTextRenderFormat()
* \since QGIS 3.4.3
*/
QgsRenderContext::TextRenderFormat textRenderFormat() const
{
return mTextRenderFormat;
}

/**
* Sets the text render \a format, which dictates how text is rendered (e.g. as paths or real text objects).
*
* \see textRenderFormat()
* \since QGIS 3.4.3
*/
void setTextRenderFormat( QgsRenderContext::TextRenderFormat format )
{
mTextRenderFormat = format;
}

//! sets format of internal QImage
void setOutputImageFormat( QImage::Format format ) { mImageFormat = format; }
//! format of internal QImage, default QImage::Format_ARGB32_Premultiplied
Expand Down Expand Up @@ -470,6 +492,8 @@ class CORE_EXPORT QgsMapSettings

QgsPathResolver mPathResolver;

QgsRenderContext::TextRenderFormat mTextRenderFormat = QgsRenderContext::TextFormatAlwaysOutlines;

#ifdef QGISDEBUG
bool mHasTransformContext = false;
#endif
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgsrendercontext.cpp
Expand Up @@ -57,6 +57,7 @@ QgsRenderContext::QgsRenderContext( const QgsRenderContext &rh )
, mSegmentationToleranceType( rh.mSegmentationToleranceType )
, mTransformContext( rh.mTransformContext )
, mPathResolver( rh.mPathResolver )
, mTextRenderFormat( rh.mTextRenderFormat )
#ifdef QGISDEBUG
, mHasTransformContext( rh.mHasTransformContext )
#endif
Expand Down Expand Up @@ -84,6 +85,7 @@ QgsRenderContext &QgsRenderContext::operator=( const QgsRenderContext &rh )
mDistanceArea = rh.mDistanceArea;
mTransformContext = rh.mTransformContext;
mPathResolver = rh.mPathResolver;
mTextRenderFormat = rh.mTextRenderFormat;
#ifdef QGISDEBUG
mHasTransformContext = rh.mHasTransformContext;
#endif
Expand Down Expand Up @@ -172,6 +174,7 @@ QgsRenderContext QgsRenderContext::fromMapSettings( const QgsMapSettings &mapSet
ctx.mDistanceArea.setEllipsoid( mapSettings.ellipsoid() );
ctx.setTransformContext( mapSettings.transformContext() );
ctx.setPathResolver( mapSettings.pathResolver() );
ctx.setTextRenderFormat( mapSettings.textRenderFormat() );
//this flag is only for stopping during the current rendering progress,
//so must be false at every new render operation
ctx.setRenderingStopped( false );
Expand Down Expand Up @@ -446,3 +449,5 @@ double QgsRenderContext::convertMetersToMapUnits( double meters ) const
}
return meters;
}


34 changes: 34 additions & 0 deletions src/core/qgsrendercontext.h
Expand Up @@ -75,6 +75,16 @@ class CORE_EXPORT QgsRenderContext
};
Q_DECLARE_FLAGS( Flags, Flag )

/**
* Options for rendering text.
* \since QGIS 3.4.3
*/
enum TextRenderFormat
{
TextFormatAlwaysOutlines, //!< Always render text using path objects (AKA outlines/curves). This always results in the best quality rendering.
TextFormatAlwaysText, //!< Always render text as text objects. This may result in rendering artefacts or poor quality rendering, depending on the text format settings.
};

/**
* Set combination of flags that will be used for rendering.
* \since QGIS 2.14
Expand Down Expand Up @@ -386,6 +396,28 @@ class CORE_EXPORT QgsRenderContext
*/
double convertMetersToMapUnits( double meters ) const;

/**
* Returns the text render format, which dictates how text is rendered (e.g. as paths or real text objects).
*
* \see setTextRenderFormat()
* \since QGIS 3.4.3
*/
TextRenderFormat textRenderFormat() const
{
return mTextRenderFormat;
}

/**
* Sets the text render \a format, which dictates how text is rendered (e.g. as paths or real text objects).
*
* \see textRenderFormat()
* \since QGIS 3.4.3
*/
void setTextRenderFormat( TextRenderFormat format )
{
mTextRenderFormat = format;
}

private:

Flags mFlags;
Expand Down Expand Up @@ -442,6 +474,8 @@ class CORE_EXPORT QgsRenderContext

QgsPathResolver mPathResolver;

TextRenderFormat mTextRenderFormat = TextFormatAlwaysOutlines;

#ifdef QGISDEBUG
bool mHasTransformContext = false;
#endif
Expand Down
60 changes: 30 additions & 30 deletions src/core/qgstextrenderer.cpp
Expand Up @@ -1708,38 +1708,38 @@ int QgsTextRenderer::sizeToPixel( double size, const QgsRenderContext &c, QgsUni
return static_cast< int >( c.convertToPainterUnits( size, unit, mapUnitScale ) + 0.5 ); //NOLINT
}

void QgsTextRenderer::drawText( const QRectF &rect, double rotation, QgsTextRenderer::HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool drawAsOutlines )
void QgsTextRenderer::drawText( const QRectF &rect, double rotation, QgsTextRenderer::HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool )
{
QgsTextFormat tmpFormat = updateShadowPosition( format );

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

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

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

void QgsTextRenderer::drawText( QPointF point, double rotation, QgsTextRenderer::HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool drawAsOutlines )
void QgsTextRenderer::drawText( QPointF point, double rotation, QgsTextRenderer::HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool )
{
QgsTextFormat tmpFormat = updateShadowPosition( format );

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

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

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

QgsTextFormat QgsTextRenderer::updateShadowPosition( const QgsTextFormat &format )
Expand All @@ -1764,7 +1764,7 @@ 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 drawAsOutlines )
const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, QgsTextRenderer::TextPart part, bool )
{
if ( !context.painter() )
{
Expand Down Expand Up @@ -1821,14 +1821,13 @@ void QgsTextRenderer::drawPart( const QRectF &rect, double rotation, HAlignment
drawTextInternal( part, context, format, component,
textLines,
&fm,
alignment,
drawAsOutlines );
alignment );
break;
}
}
}

void QgsTextRenderer::drawPart( QPointF origin, double rotation, QgsTextRenderer::HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, QgsTextRenderer::TextPart part, bool drawAsOutlines )
void QgsTextRenderer::drawPart( QPointF origin, double rotation, QgsTextRenderer::HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, QgsTextRenderer::TextPart part, bool )
{
if ( !context.painter() )
{
Expand Down Expand Up @@ -1866,7 +1865,6 @@ void QgsTextRenderer::drawPart( QPointF origin, double rotation, QgsTextRenderer
textLines,
&fm,
alignment,
drawAsOutlines,
Point );
break;
}
Expand Down Expand Up @@ -2511,9 +2509,7 @@ void QgsTextRenderer::drawTextInternal( TextPart drawType,
const Component &component,
const QStringList &textLines,
const QFontMetricsF *fontMetrics,
HAlignment alignment,
bool drawAsOutlines
, DrawMode mode )
HAlignment alignment, DrawMode mode )
{
if ( !context.painter() )
{
Expand Down Expand Up @@ -2665,21 +2661,25 @@ void QgsTextRenderer::drawTextInternal( TextPart drawType,
// scale for any print output or image saving @ specific dpi
context.painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio );

if ( drawAsOutlines )
switch ( context.textRenderFormat() )
{
// draw outlined text
_fixQPictureDPI( context.painter() );
context.painter()->drawPicture( 0, 0, textPict );
}
else
{
// draw text as text (for SVG and PDF exports)
context.painter()->setFont( format.scaledFont( context ) );
QColor textColor = format.color();
textColor.setAlphaF( format.opacity() );
context.painter()->setPen( textColor );
context.painter()->setRenderHint( QPainter::TextAntialiasing );
context.painter()->drawText( 0, 0, subComponent.text );
case QgsRenderContext::TextFormatAlwaysOutlines:
{
// draw outlined text
_fixQPictureDPI( context.painter() );
context.painter()->drawPicture( 0, 0, textPict );
break;
}

case QgsRenderContext::TextFormatAlwaysText:
{
context.painter()->setFont( format.scaledFont( context ) );
QColor textColor = format.color();
textColor.setAlphaF( format.opacity() );
context.painter()->setPen( textColor );
context.painter()->setRenderHint( QPainter::TextAntialiasing );
context.painter()->drawText( 0, 0, subComponent.text );
}
}
}
context.painter()->restore();
Expand Down

0 comments on commit 7c5a74d

Please sign in to comment.