Skip to content
Permalink
Browse files

Create custom QGIS classes for QgsTextDocument, QgsTextBlock, QgsText…

…CharacterFormat

etc

In the hope of eventually removing the QTextDocument dependancy for HTML
labels. We use this ONLY for parsing the HTML/css, and it's VERY
heavy for just these needs.
  • Loading branch information
nyalldawson committed May 11, 2020
1 parent d4fbb6c commit f2683569476562760ab7e08b592e9ea5f7d38d18
@@ -1903,6 +1903,167 @@ Returns a pixmap preview for a text ``format``.

};

class QgsTextCharacterFormat
{
%Docstring
Stores information relating to individual character formatting.

These options encapsulate formatting options which override the default
settings from a QgsTextFormat for individual characters (or sets of characters).

.. versionadded:: 3.14
%End

%TypeHeaderCode
#include "qgstextrenderer.h"
%End
public:

QgsTextCharacterFormat();

QgsTextCharacterFormat( const QTextCharFormat &format );
%Docstring
Constructor for QgsTextCharacterFormat, based on the specified QTextCharFormat ``format``.
%End

QColor textColor() const;
%Docstring
Returns the character's text color, or an invalid color if no color override
is set and the default format color should be used.

.. seealso:: :py:func:`setTextColor`
%End

void setTextColor( const QColor &textColor );
%Docstring
Sets the character's text ``color``.

Set ``color`` to an invalid color if no color override
is desired and the default format color should be used.

.. seealso:: :py:func:`textColor`
%End

};

class QgsTextFragment
{
%Docstring
Stores a fragment of text along with formatting overrides to be used when rendering the fragment.

.. versionadded:: 3.14
%End

%TypeHeaderCode
#include "qgstextrenderer.h"
%End
public:

explicit QgsTextFragment( const QString &text, const QgsTextCharacterFormat &format = QgsTextCharacterFormat() );
%Docstring
Constructor for QgsTextFragment, with the specified ``text`` and optional character ``format``.
%End

QString text() const;
%Docstring
Returns the text content of the fragment.

.. seealso:: :py:func:`setText`
%End

void setText( const QString &text );
%Docstring
Sets the ``text`` content of the fragment.

.. seealso:: :py:func:`text`
%End

const QgsTextCharacterFormat &characterFormat() const;
%Docstring
Returns the character formatting for the fragment.

.. seealso:: :py:func:`setCharacterFormat`
%End

void setCharacterFormat( const QgsTextCharacterFormat &format );
%Docstring
Sets the character ``format`` for the fragment.

.. seealso:: :py:func:`characterFormat`
%End

};


typedef QVector<QgsTextFragment> QVectorQgsTextFragmentBase;

class QgsTextBlock : QVectorQgsTextFragmentBase
{
%Docstring

Represents a block of text consisting of one or more QgsTextFragment objects.

.. versionadded:: 3.14
%End

%TypeHeaderCode
#include "qgstextrenderer.h"
#include "qvector.h"
typedef QVector<QgsTextFragment> QVectorQgsTextFragmentBase;
%End
public:

QgsTextBlock();

explicit QgsTextBlock( const QgsTextFragment &fragment );
%Docstring
Constructor for a QgsTextBlock consisting of a single text ``fragment``.
%End

};


typedef QVector<QgsTextBlock> QVectorQgsTextBlockBase;

class QgsTextDocument : QVectorQgsTextBlockBase
{
%Docstring

Represents a document consisting of one or more QgsTextBlock objects.

.. versionadded:: 3.14
%End

%TypeHeaderCode
#include "qgstextrenderer.h"
#include "qvector.h"
typedef QVector<QgsTextBlock> QVectorQgsTextBlockBase;
%End
public:

QgsTextDocument();

explicit QgsTextDocument( const QgsTextBlock &block );
%Docstring
Constructor for a QgsTextDocument consisting of a single text ``block``.
%End

explicit QgsTextDocument( const QgsTextFragment &fragment );
%Docstring
Constructor for a QgsTextDocument consisting of a single text ``fragment``.
%End

explicit QgsTextDocument( const QStringList &lines );
%Docstring
Constructor for QgsTextDocument consisting of a set of plain text ``lines``.
%End

QStringList toPlainText() const;
%Docstring
Returns a list of plain text lines of text representing the document.
%End

};

class QgsTextRenderer
{
@@ -42,7 +42,7 @@ QString QgsTextLabelFeature::text( int partId ) const
return mClusters.at( partId );
}

QTextCharFormat QgsTextLabelFeature::characterFormat( int partId ) const
QgsTextCharacterFormat QgsTextLabelFeature::characterFormat( int partId ) const
{
return mCharacterFormats.value( partId );
}
@@ -50,7 +50,7 @@ class QgsTextLabelFeature : public QgsLabelFeature
*
* \since QGIS 3.14
*/
QTextCharFormat characterFormat( int partId ) const;
QgsTextCharacterFormat characterFormat( int partId ) const;

/**
* Returns TRUE if the feature contains specific character formatting for the part with matching ID.
@@ -79,7 +79,7 @@ class QgsTextLabelFeature : public QgsLabelFeature
//! List of graphemes (used for curved labels)
QStringList mClusters;

QList< QTextCharFormat > mCharacterFormats;
QList< QgsTextCharacterFormat > mCharacterFormats;

//! Font for rendering
QFont mDefinedFont;
@@ -623,33 +623,23 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition *label, Q
component.origin = outPt;
component.rotation = label->getAlpha();

QList< QgsTextRenderer::TextBlock > textBlocks;
QgsTextDocument document;
if ( !tmpLyr.format().allowHtmlFormatting() || tmpLyr.placement == QgsPalLayerSettings::Curved )
{
QTextCharFormat c;
if ( lf->hasCharacterFormat( label->getPartId() ) )
{
c = lf->characterFormat( label->getPartId() );
}
else
{
QBrush b;
c = QTextCharFormat();
b.setColor( tmpLyr.format().color() );
c.setForeground( b );
}
const QgsTextCharacterFormat c = lf->characterFormat( label->getPartId() );
const QStringList multiLineList = QgsPalLabeling::splitToLines( txt, tmpLyr.wrapChar, tmpLyr.autoWrapLength, tmpLyr.useMaxLineLengthForAutoWrap );
for ( const QString line : multiLineList )
textBlocks << ( QgsTextRenderer::TextBlock() << QgsTextRenderer::TextFragment( line, c ) );
document << QgsTextBlock( QgsTextFragment( line, c ) );
}
else
{
QTextDocument doc;
doc.setHtml( QStringLiteral( "<span style=\"color: %1\">%2</span>" ).arg( tmpLyr.format().color().name(), txt ) );
doc.setHtml( txt );
// doc.setHtml( QStringLiteral( "<span style=\"color: %1\">%2</span>" ).arg( tmpLyr.format().color().name(), txt ) );
QTextBlock block = doc.firstBlock();
while ( true )
{
QgsTextRenderer::TextBlock blockFragments;
QgsTextBlock destDocumentBlock;
auto it = block.begin();
while ( !it.atEnd() )
{
@@ -660,31 +650,31 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition *label, Q
if ( multiLineList.size() > 1 )
{
// split this fragment over multiple blocks
blockFragments << QgsTextRenderer::TextFragment( multiLineList.at( 0 ), fragment.charFormat() );
destDocumentBlock << QgsTextFragment( multiLineList.at( 0 ), fragment.charFormat() );
for ( int lineIndex = 1; lineIndex < multiLineList.size(); ++ lineIndex )
{
textBlocks << blockFragments;
blockFragments.clear();
blockFragments << QgsTextRenderer::TextFragment( multiLineList.at( lineIndex ), fragment.charFormat() );
document << destDocumentBlock;
destDocumentBlock.clear();
destDocumentBlock << QgsTextFragment( multiLineList.at( lineIndex ), fragment.charFormat() );
}
}
else
{
blockFragments << QgsTextRenderer::TextFragment( fragment.text(), fragment.charFormat() );
destDocumentBlock << QgsTextFragment( fragment.text(), fragment.charFormat() );
}
}
it++;
}

textBlocks << blockFragments;
document << destDocumentBlock;

block = block.next();
if ( !block.isValid() )
break;
}
}

QgsTextRenderer::drawTextInternal( drawType, context, tmpLyr.format(), component, textBlocks, labelfm,
QgsTextRenderer::drawTextInternal( drawType, context, tmpLyr.format(), component, document, labelfm,
hAlign, QgsTextRenderer::Label );

}

0 comments on commit f268356

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