11
11
#include " qgsmaplayer.h"
12
12
#include " qgsmaplayerregistry.h"
13
13
#include " qgsmaplayerrenderer.h"
14
+ #include " qgsmaprenderercache.h"
14
15
#include " qgspallabeling.h"
15
16
16
17
17
18
QgsMapRendererJob::QgsMapRendererJob ( const QgsMapSettings& settings )
18
19
: mSettings(settings)
20
+ , mCache( 0 )
19
21
{
20
22
}
21
23
@@ -24,6 +26,11 @@ QgsMapRendererJob::Errors QgsMapRendererJob::errors() const
24
26
return mErrors ;
25
27
}
26
28
29
+ void QgsMapRendererJob::setCache ( QgsMapRendererCache* cache )
30
+ {
31
+ mCache = cache;
32
+ }
33
+
27
34
28
35
QgsMapRendererQImageJob::QgsMapRendererQImageJob ( const QgsMapSettings& settings )
29
36
: QgsMapRendererJob( settings )
@@ -74,6 +81,7 @@ void QgsMapRendererSequentialJob::start()
74
81
mPainter = new QPainter (&mImage );
75
82
76
83
mInternalJob = new QgsMapRendererCustomPainterJob (mSettings , mPainter );
84
+ mInternalJob ->setCache ( mCache );
77
85
78
86
connect (mInternalJob , SIGNAL (finished ()), SLOT (internalFinished ()));
79
87
@@ -115,7 +123,11 @@ QgsLabelingResults* QgsMapRendererSequentialJob::takeLabelingResults()
115
123
116
124
QImage QgsMapRendererSequentialJob::renderedImage ()
117
125
{
118
- return mImage ;
126
+ if ( isActive () && mCache )
127
+ // this will allow immediate display of cached layers and at the same time updates of the layer being rendered
128
+ return composeImage ( mSettings , mInternalJob ->jobs () );
129
+ else
130
+ return mImage ;
119
131
}
120
132
121
133
@@ -309,7 +321,8 @@ void QgsMapRendererCustomPainterJob::doRender()
309
321
mPainter ->setCompositionMode ( job.blendMode );
310
322
}
311
323
312
- job.renderer ->render ();
324
+ if ( !job.cached )
325
+ job.renderer ->render ();
313
326
314
327
if ( job.img )
315
328
{
@@ -496,6 +509,12 @@ LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter* painter, QgsPalLabelin
496
509
QListIterator<QString> li ( mSettings .layers () );
497
510
li.toBack ();
498
511
512
+ if ( mCache )
513
+ {
514
+ bool cacheValid = mCache ->init ( mSettings .visibleExtent (), mSettings .scale () );
515
+ qDebug (" CACHE VALID: %d" , cacheValid);
516
+ }
517
+
499
518
while ( li.hasPrevious () )
500
519
{
501
520
QString layerId = li.previous ();
@@ -542,38 +561,56 @@ LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter* painter, QgsPalLabelin
542
561
}
543
562
}
544
563
545
- // Flattened image for drawing when a blending mode is set
546
- QImage * mypFlattenedImage = 0 ;
547
-
548
- // If we are drawing with an alternative blending mode then we need to render to a separate image
549
- // before compositing this on the map. This effectively flattens the layer and prevents
550
- // blending occuring between objects on the layer
551
- if ( !painter || needTemporaryImage ( ml ) )
564
+ // Force render of layers that are being edited
565
+ // or if there's a labeling engine that needs the layer to register features
566
+ if ( mCache && ml->type () == QgsMapLayer::VectorLayer )
552
567
{
553
- mypFlattenedImage = new QImage ( mSettings .outputSize ().width (),
554
- mSettings .outputSize ().height (), QImage::Format_ARGB32 );
555
- if ( mypFlattenedImage->isNull () )
556
- {
557
- mErrors .append ( Error ( layerId, " Insufficient memory for image " + QString::number ( mSettings .outputSize ().width () ) + " x" + QString::number ( mSettings .outputSize ().height () ) ) );
558
- delete mypFlattenedImage;
559
- continue ;
560
- }
561
- mypFlattenedImage->fill ( 0 );
568
+ QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
569
+ if ( vl->isEditable () || ( labelingEngine && labelingEngine->willUseLayer ( vl ) ) )
570
+ mCache ->setCacheImage ( ml->id (), QImage () );
562
571
}
563
572
564
573
layerJobs.append ( LayerRenderJob () );
565
574
LayerRenderJob& job = layerJobs.last ();
575
+ job.cached = false ;
566
576
job.img = 0 ;
567
577
job.blendMode = ml->blendMode ();
578
+ job.layerId = ml->id ();
568
579
569
580
job.context = QgsRenderContext::fromMapSettings ( mSettings );
570
581
job.context .setPainter ( painter );
571
582
job.context .setLabelingEngine ( labelingEngine );
572
583
job.context .setCoordinateTransform ( ct );
573
584
job.context .setExtent ( r1 );
574
585
575
- if ( mypFlattenedImage )
586
+ // if we can use the cache, let's do it and avoid rendering!
587
+ if ( mCache && !mCache ->cacheImage ( ml->id () ).isNull () )
576
588
{
589
+ job.cached = true ;
590
+ job.img = new QImage ( mCache ->cacheImage ( ml->id () ) );
591
+ job.renderer = 0 ;
592
+ job.context .setPainter ( 0 );
593
+ continue ;
594
+ }
595
+
596
+ // If we are drawing with an alternative blending mode then we need to render to a separate image
597
+ // before compositing this on the map. This effectively flattens the layer and prevents
598
+ // blending occuring between objects on the layer
599
+ if ( mCache || !painter || needTemporaryImage ( ml ) )
600
+ {
601
+ // Flattened image for drawing when a blending mode is set
602
+ QImage * mypFlattenedImage = 0 ;
603
+ mypFlattenedImage = new QImage ( mSettings .outputSize ().width (),
604
+ mSettings .outputSize ().height (), QImage::Format_ARGB32_Premultiplied );
605
+ if ( mypFlattenedImage->isNull () )
606
+ {
607
+ mErrors .append ( Error ( layerId, " Insufficient memory for image " + QString::number ( mSettings .outputSize ().width () ) + " x" + QString::number ( mSettings .outputSize ().height () ) ) );
608
+ delete mypFlattenedImage;
609
+ layerJobs.removeLast ();
610
+ continue ;
611
+ }
612
+ mypFlattenedImage->fill ( 0 );
613
+
577
614
job.img = mypFlattenedImage;
578
615
QPainter* mypPainter = new QPainter ( job.img );
579
616
mypPainter->setRenderHint ( QPainter::Antialiasing, mSettings .testFlag ( QgsMapSettings::Antialiasing ) );
@@ -603,18 +640,28 @@ void QgsMapRendererJob::cleanupJobs( LayerRenderJobs& jobs )
603
640
{
604
641
LayerRenderJob& job = *it;
605
642
if ( job.img )
606
- {
643
+ {
607
644
delete job.context .painter ();
608
645
job.context .setPainter ( 0 );
646
+
647
+ if ( mCache && !job.cached && !job.context .renderingStopped () )
648
+ {
649
+ qDebug (" caching image for %s" , job.layerId .toAscii ().data ());
650
+ mCache ->setCacheImage ( job.layerId , *job.img );
651
+ }
652
+
609
653
delete job.img ;
610
654
job.img = 0 ;
611
655
}
612
656
613
- foreach ( QString message, job.renderer ->errors () )
614
- mErrors .append ( Error ( job.renderer ->layerID (), message ) );
657
+ if ( job.renderer )
658
+ {
659
+ foreach ( QString message, job.renderer ->errors () )
660
+ mErrors .append ( Error ( job.renderer ->layerID (), message ) );
615
661
616
- delete job.renderer ;
617
- job.renderer = 0 ;
662
+ delete job.renderer ;
663
+ job.renderer = 0 ;
664
+ }
618
665
}
619
666
620
667
jobs.clear ();
@@ -752,7 +799,7 @@ QgsLabelingResults* QgsMapRendererParallelJob::takeLabelingResults()
752
799
QImage QgsMapRendererParallelJob::renderedImage ()
753
800
{
754
801
if ( mStatus == RenderingLayers )
755
- return composeImage ();
802
+ return composeImage ( mSettings , mLayerJobs );
756
803
else
757
804
return mFinalImage ; // when rendering labels or idle
758
805
}
@@ -762,7 +809,7 @@ void QgsMapRendererParallelJob::renderLayersFinished()
762
809
Q_ASSERT ( mStatus == RenderingLayers );
763
810
764
811
// compose final image
765
- mFinalImage = composeImage ();
812
+ mFinalImage = composeImage ( mSettings , mLayerJobs );
766
813
767
814
cleanupJobs ( mLayerJobs );
768
815
@@ -798,6 +845,9 @@ void QgsMapRendererParallelJob::renderLayerStatic(LayerRenderJob& job)
798
845
if ( job.context .renderingStopped () )
799
846
return ;
800
847
848
+ if ( job.cached )
849
+ return ;
850
+
801
851
QTime t;
802
852
t.start ();
803
853
QgsDebugMsg ( QString (" job %1 start" ).arg ( (ulong) &job, 0 , 16 ) );
@@ -817,14 +867,14 @@ void QgsMapRendererParallelJob::renderLabelsStatic(QgsMapRendererParallelJob* se
817
867
}
818
868
819
869
820
- QImage QgsMapRendererParallelJob ::composeImage ()
870
+ QImage QgsMapRendererJob ::composeImage ( const QgsMapSettings& settings, const LayerRenderJobs& jobs )
821
871
{
822
- QImage image ( mSettings .outputSize (), QImage::Format_ARGB32_Premultiplied );
823
- image.fill ( mSettings .backgroundColor ().rgb () );
872
+ QImage image ( settings .outputSize (), QImage::Format_ARGB32_Premultiplied );
873
+ image.fill ( settings .backgroundColor ().rgb () );
824
874
825
875
QPainter painter (&image);
826
876
827
- for (LayerRenderJobs::const_iterator it = mLayerJobs . begin (); it != mLayerJobs . end (); ++it)
877
+ for (LayerRenderJobs::const_iterator it = jobs. constBegin (); it != jobs. constEnd (); ++it)
828
878
{
829
879
const LayerRenderJob& job = *it;
830
880
0 commit comments