@@ -154,8 +154,7 @@ void QgsTextRenderer::drawPart( const QRectF &rect, double rotation, QgsTextRend
154
154
component.center = rect.center ();
155
155
}
156
156
157
- const QStringList lines = document.toPlainText ();
158
- QgsTextRenderer::drawBackground ( context, component, format, lines, Rect );
157
+ QgsTextRenderer::drawBackground ( context, component, format, document, Rect );
159
158
160
159
break ;
161
160
}
@@ -205,8 +204,7 @@ void QgsTextRenderer::drawPart( QPointF origin, double rotation, QgsTextRenderer
205
204
if ( !format.background ().enabled () )
206
205
return ;
207
206
208
- const QStringList lines = document.toPlainText ();
209
- QgsTextRenderer::drawBackground ( context, component, format, lines, Point );
207
+ QgsTextRenderer::drawBackground ( context, component, format, document, Point );
210
208
break ;
211
209
}
212
210
@@ -447,35 +445,60 @@ void QgsTextRenderer::drawMask( QgsRenderContext &context, const QgsTextRenderer
447
445
p->restore ();
448
446
}
449
447
450
- double QgsTextRenderer::textWidth ( const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, QFontMetricsF *fontMetrics )
448
+ double QgsTextRenderer::textWidth ( const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, QFontMetricsF * )
451
449
{
452
- // calculate max width of text lines
453
- std::unique_ptr< QFontMetricsF > newFm;
454
- if ( !fontMetrics )
450
+ if ( !format.allowHtmlFormatting () )
455
451
{
456
- newFm.reset ( new QFontMetricsF ( format.scaledFont ( context ) ) );
457
- fontMetrics = newFm.get ();
452
+ return textWidth ( context, format, QgsTextDocument::fromPlainText ( textLines ) );
458
453
}
454
+ else
455
+ {
456
+ return textWidth ( context, format, QgsTextDocument::fromHtml ( textLines ) );
457
+ }
458
+ }
459
+
460
+ double QgsTextRenderer::textWidth ( const QgsRenderContext &context, const QgsTextFormat &format, const QgsTextDocument &document )
461
+ {
462
+ // calculate max width of text lines
463
+ const QFont baseFont = format.scaledFont ( context );
459
464
460
465
double width = 0 ;
461
466
switch ( format.orientation () )
462
467
{
463
468
case QgsTextFormat::HorizontalOrientation:
464
469
{
465
470
double maxLineWidth = 0 ;
466
- const auto constTextLines = textLines;
467
- for ( const QString &line : constTextLines )
471
+ for ( const QgsTextBlock &block : document )
468
472
{
469
- maxLineWidth = std::max ( maxLineWidth, fontMetrics->width ( line ) );
473
+ double blockWidth = 0 ;
474
+ for ( const QgsTextFragment &fragment : block )
475
+ {
476
+ blockWidth += fragment.horizontalAdvance ( baseFont );
477
+ }
478
+ maxLineWidth = std::max ( maxLineWidth, blockWidth );
470
479
}
471
480
width = maxLineWidth;
472
481
break ;
473
482
}
474
483
475
484
case QgsTextFormat::VerticalOrientation:
476
485
{
477
- double labelWidth = fontMetrics->maxWidth ();
478
- width = labelWidth + ( textLines.size () - 1 ) * labelWidth * format.lineHeight ();
486
+ double totalLineWidth = 0 ;
487
+ int blockIndex = 0 ;
488
+ for ( const QgsTextBlock &block : document )
489
+ {
490
+ double blockWidth = 0 ;
491
+ for ( const QgsTextFragment &fragment : block )
492
+ {
493
+ QFont fragmentFont = baseFont;
494
+ fragment.characterFormat ().updateFontForFormat ( fragmentFont );
495
+ blockWidth = std::max ( QFontMetricsF ( fragmentFont ).maxWidth (), blockWidth );
496
+ }
497
+
498
+ totalLineWidth += blockIndex == 0 ? blockWidth : blockWidth * format.lineHeight ();
499
+ blockIndex++;
500
+ }
501
+ width = totalLineWidth;
479
502
break ;
480
503
}
481
504
@@ -489,49 +512,92 @@ double QgsTextRenderer::textWidth( const QgsRenderContext &context, const QgsTex
489
512
return width;
490
513
}
491
514
492
- double QgsTextRenderer::textHeight ( const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, DrawMode mode, QFontMetricsF *fontMetrics )
515
+ double QgsTextRenderer::textHeight ( const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, DrawMode mode, QFontMetricsF * )
493
516
{
494
- // calculate max width of text lines
495
- std::unique_ptr< QFontMetricsF > newFm;
496
- if ( !fontMetrics )
517
+ if ( !format.allowHtmlFormatting () )
497
518
{
498
- newFm.reset ( new QFontMetricsF ( format.scaledFont ( context ) ) );
499
- fontMetrics = newFm.get ();
519
+ return textHeight ( context, format, QgsTextDocument::fromPlainText ( textLines ), mode );
500
520
}
521
+ else
522
+ {
523
+ return textHeight ( context, format, QgsTextDocument::fromHtml ( textLines ), mode );
524
+ }
525
+ }
526
+
527
+ double QgsTextRenderer::textHeight ( const QgsRenderContext &context, const QgsTextFormat &format, const QgsTextDocument &document, DrawMode mode )
528
+ {
529
+ // calculate max height of text lines
530
+
531
+ const QFont baseFont = format.scaledFont ( context );
501
532
502
533
switch ( format.orientation () )
503
534
{
504
535
case QgsTextFormat::HorizontalOrientation:
505
536
{
506
- double labelHeight = fontMetrics->ascent () + fontMetrics->descent (); // ignore +1 for baseline
507
- switch ( mode )
537
+ int blockIndex = 0 ;
538
+ double totalHeight = 0 ;
539
+ for ( const QgsTextBlock &block : document )
508
540
{
509
- case Label:
510
- // rendering labels needs special handling - in this case text should be
511
- // drawn with the bottom left corner coinciding with origin, vs top left
512
- // for standard text rendering. Line height is also slightly different.
513
- return labelHeight + ( textLines.size () - 1 ) * labelHeight * format.lineHeight ();
541
+ double maxBlockHeight = 0 ;
542
+ double maxBlockLineSpacing = 0 ;
543
+ for ( const QgsTextFragment &fragment : block )
544
+ {
545
+ QFont fragmentFont = baseFont;
546
+ fragment.characterFormat ().updateFontForFormat ( fragmentFont );
547
+ const QFontMetricsF fm ( fragmentFont );
514
548
515
- case Rect:
516
- case Point:
517
- // standard rendering - designed to exactly replicate QPainter's drawText method
518
- return labelHeight + ( textLines.size () - 1 ) * fontMetrics->lineSpacing () * format.lineHeight ();
549
+ const double fragmentHeight = fm.ascent () + fm.descent (); // ignore +1 for baseline
550
+
551
+ maxBlockHeight = std::max ( maxBlockHeight, fragmentHeight );
552
+ maxBlockLineSpacing = std::max ( maxBlockLineSpacing, fm.lineSpacing () );
553
+ }
554
+
555
+ switch ( mode )
556
+ {
557
+ case Label:
558
+ // rendering labels needs special handling - in this case text should be
559
+ // drawn with the bottom left corner coinciding with origin, vs top left
560
+ // for standard text rendering. Line height is also slightly different.
561
+ totalHeight += blockIndex == 0 ? maxBlockHeight : maxBlockHeight * format.lineHeight ();
562
+ break ;
563
+
564
+ case Rect:
565
+ case Point:
566
+ // standard rendering - designed to exactly replicate QPainter's drawText method
567
+ totalHeight += blockIndex == 0 ? maxBlockHeight : maxBlockLineSpacing * format.lineHeight ();
568
+ break ;
569
+ }
570
+
571
+ blockIndex++;
519
572
}
520
- break ;
573
+
574
+ return totalHeight;
521
575
}
522
576
523
577
case QgsTextFormat::VerticalOrientation:
524
578
{
525
- double labelHeight = fontMetrics->ascent ();
526
- double letterSpacing = format.scaledFont ( context ).letterSpacing ();
527
- int maxLineLength = 0 ;
528
- for ( const auto &line : textLines )
579
+ double maxBlockHeight = 0 ;
580
+ for ( const QgsTextBlock &block : document )
529
581
{
530
- if ( line.length () > maxLineLength )
531
- maxLineLength = line.length ();
582
+ double blockHeight = 0 ;
583
+ int fragmentIndex = 0 ;
584
+ for ( const QgsTextFragment &fragment : block )
585
+ {
586
+ QFont fragmentFont = baseFont;
587
+ fragment.characterFormat ().updateFontForFormat ( fragmentFont );
588
+ const QFontMetricsF fm ( fragmentFont );
589
+
590
+ const double labelHeight = fm.ascent ();
591
+ const double letterSpacing = fragmentFont.letterSpacing ();
592
+
593
+ blockHeight += fragmentIndex = 0 ? labelHeight * fragment.text ().size () + ( fragment.text ().size () - 1 ) * letterSpacing
594
+ : fragment.text ().size () * ( labelHeight + letterSpacing );
595
+ fragmentIndex++;
596
+ }
597
+ maxBlockHeight = std::max ( maxBlockHeight, blockHeight );
532
598
}
533
- return labelHeight * maxLineLength + ( maxLineLength - 1 ) * letterSpacing;
534
- break ;
599
+
600
+ return maxBlockHeight ;
535
601
}
536
602
537
603
case QgsTextFormat::RotationBasedOrientation:
@@ -544,8 +610,7 @@ double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTe
544
610
return 0 ;
545
611
}
546
612
547
- void QgsTextRenderer::drawBackground ( QgsRenderContext &context, QgsTextRenderer::Component component, const QgsTextFormat &format,
548
- const QStringList &textLines, DrawMode mode )
613
+ void QgsTextRenderer::drawBackground ( QgsRenderContext &context, QgsTextRenderer::Component component, const QgsTextFormat &format, const QgsTextDocument &document, QgsTextRenderer::DrawMode mode )
549
614
{
550
615
QgsTextBackgroundSettings background = format.background ();
551
616
@@ -578,8 +643,8 @@ void QgsTextRenderer::drawBackground( QgsRenderContext &context, QgsTextRenderer
578
643
{
579
644
// need to calculate size of text
580
645
QFontMetricsF fm ( format.scaledFont ( context ) );
581
- double width = textWidth ( context, format, textLines, &fm );
582
- double height = textHeight ( context, format, textLines , mode, &fm );
646
+ double width = textWidth ( context, format, document );
647
+ double height = textHeight ( context, format, document , mode );
583
648
584
649
switch ( mode )
585
650
{
0 commit comments