Skip to content

Commit

Permalink
Fix crash on drawing curved text with zero width characters
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Oct 30, 2024
1 parent f0a7b63 commit 468b13d
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 2 deletions.
8 changes: 6 additions & 2 deletions src/core/textrenderer/qgstextrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,11 @@ void QgsTextRenderer::drawDocumentOnLine( const QPolygonF &line, const QgsTextFo
if ( placement->graphemePlacement.empty() )
return;

std::vector< QgsTextRenderer::Component > components;
// We may have deliberately skipped over some graphemes during curved text placement (such as zero-width graphemes).
// So we need to use a hash of the original grapheme index to place generated components in, as there may accordingly
// be graphemes which don't result in components, and we can't just blindly assume the component array position
// will match the original grapheme index
QHash< int, QgsTextRenderer::Component > components;
components.reserve( placement->graphemePlacement.size() );
for ( const QgsTextRendererUtils::CurvedGraphemePlacement &grapheme : std::as_const( placement->graphemePlacement ) )
{
Expand All @@ -320,7 +324,7 @@ void QgsTextRenderer::drawDocumentOnLine( const QPolygonF &line, const QgsTextFo
component.origin.ry() += verticalOffset * std::sin( grapheme.angle + M_PI_2 );
}

components.emplace_back( component );
components.insert( grapheme.graphemeIndex, component );
}

if ( format.background().enabled() )
Expand Down
36 changes: 36 additions & 0 deletions tests/src/python/test_qgstextrenderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4456,6 +4456,42 @@ def testDrawTextOnLineAtStart(self):
painter.end()
self.assertTrue(self.image_check('text_on_line_at_start', 'text_on_line_at_start', image, 'text_on_line_at_start'))

def testDrawTextOnLineZeroWidthChar(self):
format = QgsTextFormat()
format.setFont(getTestFont('bold'))
format.setSize(16)
format.setSizeUnit(QgsUnitTypes.RenderUnit.RenderPoints)
format.background().setEnabled(True)

image = QImage(400, 400, QImage.Format.Format_RGB32)

painter = QPainter()
ms = QgsMapSettings()
ms.setExtent(QgsRectangle(0, 0, 50, 50))
ms.setOutputSize(image.size())
context = QgsRenderContext.fromMapSettings(ms)
context.setPainter(painter)
context.setScaleFactor(96 / 25.4) # 96 DPI
context.setFlag(QgsRenderContext.Flag.ApplyScalingWorkaroundForTextRendering, True)

painter.begin(image)
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
image.fill(QColor(152, 219, 249))

painter.setBrush(Qt.BrushStyle.NoBrush)
painter.setPen(QPen(QColor(0, 0, 0)))

line = QPolygonF([QPointF(50, 200), QPointF(350, 200)])
painter.drawPolygon(line)

painter.setBrush(QBrush(QColor(182, 239, 255)))
painter.setPen(Qt.PenStyle.NoPen)

QgsTextRenderer.drawTextOnLine(line, 'b\r\na', context, format, 0)

painter.end()
self.assertTrue(self.image_check('text_on_curved_line_zero_width_char', 'text_on_curved_line_zero_width_char', image, 'text_on_curved_line_zero_width_char'))

def testDrawTextOnLineAtOffset(self):
format = QgsTextFormat()
format.setFont(getTestFont('bold'))
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 468b13d

Please sign in to comment.